Compare commits

...

60 Commits

Author SHA1 Message Date
Sebastián Ramírez
7e9d5aacf8 🔖 Release version 0.66.0 2021-07-04 20:59:46 +02:00
Sebastián Ramírez
d27a218bc3 📝 Update release notes 2021-07-04 20:58:49 +02:00
github-actions
0c4ded88fe 📝 Update release notes 2021-07-04 18:54:19 +00:00
Rubikoid
0e0931d308 🐛 Fix include/exclude for dicts in jsonable_encoder (#2016)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-04 20:53:40 +02:00
github-actions
dcfa9eb8fe 📝 Update release notes 2021-07-04 17:35:19 +00:00
Camila Gutierrez
6ebf60b175 🌐 Add Spanish translation for tutorial/query-params.md (#2243)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-04 19:34:46 +02:00
github-actions
a4d0724a97 📝 Update release notes 2021-07-04 17:06:51 +00:00
Juan Funez
c235e9b78c 🌐 Add Spanish translation for advanced/response-directly.md (#1253)
Co-authored-by: Camila Gutierrez <mariacamilagl30@gmail.com>
2021-07-04 19:06:18 +02:00
github-actions
5fa3e239db 📝 Update release notes 2021-07-04 14:15:04 +00:00
Juan Funez
3d1b107d70 🌐 Add Spanish translation for advanced/additional-status-codes.md (#1252)
Co-authored-by: Camila Gutierrez <mariacamilagl30@gmail.com>
2021-07-04 16:14:29 +02:00
github-actions
18e0828daf 📝 Update release notes 2021-07-04 12:50:02 +00:00
Juan Funez
f16c7729bd 🌐 Add Spanish translation for advanced/path-operation-advanced-configuration.md (#1251)
Co-authored-by: Camila Gutierrez <mariacamilagl@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
Co-authored-by: Camila Gutierrez <mariacamilagl30@gmail.com>
2021-07-04 14:49:31 +02:00
Sebastián Ramírez
9f3c8cd139 📝 Update release notes, add links to docs 2021-07-03 21:59:39 +02:00
github-actions
a7a35aee61 📝 Update release notes 2021-07-03 19:52:03 +00:00
Sebastián Ramírez
dc5a966548 Allow setting the response_class to RedirectResponse and returning the URL from the function (#3457) 2021-07-03 21:51:28 +02:00
github-actions
ea8d7f689e 📝 Update release notes 2021-07-03 17:16:33 +00:00
Jacob Magnusson
0ed6c92341 🐛 Support custom OpenAPI / JSON Schema fields in the generated output OpenAPI (#1429)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-03 19:15:59 +02:00
Sebastián Ramírez
79f52c76cf 🔖 Release version 0.65.3 2021-07-03 18:33:32 +02:00
Sebastián Ramírez
b725e9eb45 📝 Update release notes 2021-07-03 18:32:50 +02:00
Sebastián Ramírez
787e54b096 📝 Update release notes 2021-07-03 18:30:46 +02:00
github-actions
15fd60b29a 📝 Update release notes 2021-07-03 16:26:48 +00:00
Sebastián Ramírez
edf6b2d61f ♻ Assume request bodies contain JSON when no Content-Type header is provided (#3456) 2021-07-03 18:25:12 +02:00
github-actions
7eb17fc874 📝 Update release notes 2021-07-03 15:13:30 +00:00
Nasaruddin
7e4bfaf0e9 🌐 Initialize Indonesian translations (#3014)
Co-authored-by: Nasaruddin <nasaruddin@skorpoints.com>
2021-07-03 17:12:51 +02:00
github-actions
e1d4fc5325 📝 Update release notes 2021-07-03 14:47:21 +00:00
Camila Gutierrez
faec748ef6 🌐 Add Spanish translation of Tutorial - Path Parameters (#2219)
Co-authored-by: Pedro A. Moreno <pedabraham@gmail.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-03 16:46:49 +02:00
github-actions
afec8c4580 📝 Update release notes 2021-07-03 14:14:01 +00:00
Camila Gutierrez
8a1f0aa3b6 🌐 Add Spanish translation of Tutorial - First Steps (#2208)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-03 16:13:28 +02:00
github-actions
f784644510 📝 Update release notes 2021-07-02 15:18:24 +00:00
github-actions[bot]
710a2f745c 👥 Update FastAPI People (#3450)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-02 17:17:49 +02:00
github-actions
bd230fe473 📝 Update release notes 2021-07-02 15:00:53 +00:00
Mário Victor Ribeiro Silva
9c5b000956 🌐 Portuguese translation of Tutorial - Body - Fields (#3420)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-02 17:00:11 +02:00
github-actions
a9f2a25feb 📝 Update release notes 2021-07-02 14:54:56 +00:00
jaystone776
c00c2d1ecf 🌐 Add Chinese translation for Tutorial - Request - Forms - and - Files (#3249)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-02 16:54:22 +02:00
github-actions
dd7bbae837 📝 Update release notes 2021-07-02 14:44:04 +00:00
jaystone776
0a84d48a82 🌐 Add Chinese translation for Tutorial - Handling - Errors (#3299)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-02 16:43:28 +02:00
github-actions
e5d0b97dee 📝 Update release notes 2021-07-02 14:36:34 +00:00
jaystone776
811c3f873f 🌐 Add Chinese translation for Tutorial - Form - Data (#3248)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-02 16:35:58 +02:00
github-actions
662fc81544 📝 Update release notes 2021-07-02 14:27:36 +00:00
github-actions[bot]
5e2f2d541d 👥 Update FastAPI People (#3319)
Co-authored-by: github-actions <github-actions@github.com>
2021-07-02 16:27:02 +02:00
github-actions
8116d8158b 📝 Update release notes 2021-07-02 14:24:16 +00:00
jaystone776
e6836781d5 🌐 Add Chinese translation for Tutorial - Body - Updates (#3237)
Co-authored-by: Xie Wei <ampedee@gmail.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-02 16:23:41 +02:00
github-actions
098088c763 📝 Update release notes 2021-07-02 14:21:11 +00:00
Hareru
4bf9a52043 🌐 Add Chinese translation for FastAPI People (#3112)
Co-authored-by: Xie Wei <ampedee@gmail.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-02 16:20:36 +02:00
github-actions
eb6f964ede 📝 Update release notes 2021-07-02 14:18:44 +00:00
Sam Courtemanche
4473a9bcbf 🌐 Add French translation for Project Generation (#3197)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-02 16:18:06 +02:00
github-actions
fdc7c96ece 📝 Update release notes 2021-07-02 14:14:28 +00:00
Sam Courtemanche
a694be81ae 🌐 Add French translation for Python Types Intro (#3185) 2021-07-02 16:13:52 +02:00
github-actions
0abb743e9c 📝 Update release notes 2021-07-02 14:12:43 +00:00
Sam Courtemanche
acda3f06b0 🌐 Add French translation for External Links (#3103)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-02 16:12:05 +02:00
github-actions
3127bc4e05 📝 Update release notes 2021-07-02 14:06:45 +00:00
Ruidy
18b24df9c8 🌐 Add French translation for Alternatives, Inspiration and Comparisons (#3020)
Co-authored-by: Jérôme Fink <jerome.fink@student.unamur.be>
Co-authored-by: Sam Courtemanche <sam.courtemanche.ipod@gmail.com>
2021-07-02 16:06:10 +02:00
github-actions
b27758fe13 📝 Update release notes 2021-07-02 14:03:22 +00:00
BoYanZh
a0b2006230 🌐 Fix Chinese translation code snippet mismatch in Tutorial - Python Types Intro 2021-07-02 16:02:45 +02:00
github-actions
bd143ffa5a 📝 Update release notes 2021-07-02 13:43:04 +00:00
Fabio Serrao
77c1988a8b 🌐 Add Portuguese translation for Development Contributing (#1364) 2021-07-02 15:42:29 +02:00
github-actions
26a36f79fa 📝 Update release notes 2021-06-29 21:23:00 +00:00
Sebastián Ramírez
97d8d4016b ⬆ Upgrade docs development dependency on typer-cli to >=0.0.12 to fix conflicts (#3429) 2021-06-29 23:22:23 +02:00
github-actions
246e80512d 📝 Update release notes 2021-06-29 12:24:59 +00:00
jaystone776
fc6827d68a 🌐 Add Chinese translation for Tutorial - Request - Files (#3244)
Co-authored-by: Xie Wei <ampedee@gmail.com>
2021-06-29 14:24:19 +02:00
57 changed files with 4586 additions and 153 deletions

View File

@@ -26,7 +26,7 @@ jobs:
run: python3.7 -m pip install flit
- name: Install docs extras
if: steps.cache.outputs.cache-hit != 'true'
run: python3.7 -m flit install --extras doc
run: python3.7 -m flit install --deps production --extras doc
- name: Install Material for MkDocs Insiders
if: github.event.pull_request.head.repo.fork == false && steps.cache.outputs.cache-hit != 'true'
run: pip install git+https://${{ secrets.ACTIONS_TOKEN }}@github.com/squidfunk/mkdocs-material-insiders.git

View File

@@ -1,24 +1,24 @@
maintainers:
- login: tiangolo
answers: 1221
prs: 222
answers: 1225
prs: 232
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=05f95ca7fdead36edd9c86be46b4ef6c3c71f876&v=4
url: https://github.com/tiangolo
experts:
- login: Kludex
count: 267
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
url: https://github.com/Kludex
- login: dmontagu
count: 262
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
url: https://github.com/dmontagu
- login: Kludex
count: 240
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
url: https://github.com/Kludex
- login: ycd
count: 211
count: 216
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4
url: https://github.com/ycd
- login: Mause
count: 174
count: 182
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
url: https://github.com/Mause
- login: euri10
@@ -29,22 +29,22 @@ experts:
count: 130
avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4
url: https://github.com/phy25
- login: ArcLightSlavik
count: 64
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=81a84af39c89b898b0fbc5a04e8834f60f23e55a&v=4
url: https://github.com/ArcLightSlavik
- login: falkben
count: 56
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
url: https://github.com/falkben
- login: ArcLightSlavik
count: 50
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=6e53b1a2f340d77429d435babcec107c7cc50972&v=4
url: https://github.com/ArcLightSlavik
- login: raphaelauv
count: 47
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
url: https://github.com/raphaelauv
- login: sm-Fifteen
count: 46
avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4
url: https://github.com/sm-Fifteen
- login: raphaelauv
count: 41
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
url: https://github.com/raphaelauv
- login: includeamin
count: 38
avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4
@@ -54,7 +54,7 @@ experts:
avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4
url: https://github.com/prostomarkeloff
- login: Dustyposa
count: 31
count: 32
avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4
url: https://github.com/Dustyposa
- login: krishnardt
@@ -77,6 +77,10 @@ experts:
count: 24
avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4
url: https://github.com/SirTelemak
- login: chbndrhnns
count: 22
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
url: https://github.com/chbndrhnns
- login: acnebs
count: 22
avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=bfd127b3e6200f4d00afd714f0fc95c2512df19b&v=4
@@ -85,6 +89,10 @@ experts:
count: 22
avatarUrl: https://avatars.githubusercontent.com/u/22559461?u=a9cc3238217e21dc8796a1a500f01b722adb082c&v=4
url: https://github.com/nsidnev
- login: frankie567
count: 21
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=72adf1cb1d29787305c99700d669561952cea0af&v=4
url: https://github.com/frankie567
- login: chris-allnutt
count: 21
avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4
@@ -93,6 +101,10 @@ experts:
count: 19
avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4
url: https://github.com/retnikt
- login: Hultner
count: 18
avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4
url: https://github.com/Hultner
- login: jorgerpo
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4
@@ -101,22 +113,18 @@ experts:
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/28262306?u=66ee21316275ef356081c2efc4ed7a4572e690dc&v=4
url: https://github.com/nkhitrov
- login: chbndrhnns
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
url: https://github.com/chbndrhnns
- login: waynerv
count: 14
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
url: https://github.com/waynerv
- login: haizaar
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/58201?u=4f1f9843d69433ca0d380d95146cfe119e5fdac4&v=4
url: https://github.com/haizaar
- login: frankie567
- login: acidjunk
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=72adf1cb1d29787305c99700d669561952cea0af&v=4
url: https://github.com/frankie567
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
url: https://github.com/acidjunk
- login: zamiramir
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/40475662?u=e58ef61034e8d0d6a312cc956fb09b9c3332b449&v=4
@@ -139,25 +147,37 @@ experts:
url: https://github.com/stefanondisponibile
last_month_active:
- login: Kludex
count: 13
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
url: https://github.com/Kludex
- login: ycd
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4
url: https://github.com/ycd
- login: raphaelauv
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
url: https://github.com/raphaelauv
- login: frankie567
count: 5
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=72adf1cb1d29787305c99700d669561952cea0af&v=4
url: https://github.com/frankie567
- login: insomnes
- login: Mause
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
url: https://github.com/Mause
- login: ArcLightSlavik
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=81a84af39c89b898b0fbc5a04e8834f60f23e55a&v=4
url: https://github.com/ArcLightSlavik
- login: gyKa
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
url: https://github.com/insomnes
avatarUrl: https://avatars.githubusercontent.com/u/1000842?v=4
url: https://github.com/gyKa
- login: ricky-sb
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/10700079?v=4
url: https://github.com/ricky-sb
- login: captainCapitalism
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/32553875?v=4
url: https://github.com/captainCapitalism
- login: acidjunk
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
url: https://github.com/acidjunk
top_contributors:
- login: waynerv
count: 25
@@ -184,7 +204,7 @@ top_contributors:
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=706e1ee3f248245f2d68b976d149d06fd5a2010d&v=4
url: https://github.com/RunningIkkyu
- login: Serrones
count: 6
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
url: https://github.com/Serrones
- login: hard-coders
@@ -211,29 +231,33 @@ top_contributors:
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=5a44657c0544111ee3c132d9bb9951c2804f7969&v=4
url: https://github.com/komtaki
- login: Smlep
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
url: https://github.com/Smlep
top_reviewers:
- login: Kludex
count: 75
count: 80
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
url: https://github.com/Kludex
- login: tokusumi
count: 44
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
url: https://github.com/tokusumi
- login: ycd
count: 39
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4
url: https://github.com/ycd
- login: Laineyzhang55
count: 34
count: 42
avatarUrl: https://avatars.githubusercontent.com/u/59285379?v=4
url: https://github.com/Laineyzhang55
- login: ycd
count: 41
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4
url: https://github.com/ycd
- login: waynerv
count: 32
count: 38
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
url: https://github.com/waynerv
- login: AdrianDeAnda
count: 26
count: 28
avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=bb7f8a0d6c9de4e9d0320a9f271210206e202250&v=4
url: https://github.com/AdrianDeAnda
- login: dmontagu
@@ -244,6 +268,14 @@ top_reviewers:
count: 21
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=5a44657c0544111ee3c132d9bb9951c2804f7969&v=4
url: https://github.com/komtaki
- login: ArcLightSlavik
count: 20
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=81a84af39c89b898b0fbc5a04e8834f60f23e55a&v=4
url: https://github.com/ArcLightSlavik
- login: cassiobotaro
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4
url: https://github.com/cassiobotaro
- login: yanever
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/21978760?v=4
@@ -260,18 +292,10 @@ top_reviewers:
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/63476957?u=6c86e59b48e0394d4db230f37fc9ad4d7e2c27c7&v=4
url: https://github.com/delhi09
- login: cassiobotaro
count: 14
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4
url: https://github.com/cassiobotaro
- login: RunningIkkyu
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=706e1ee3f248245f2d68b976d149d06fd5a2010d&v=4
url: https://github.com/RunningIkkyu
- login: ArcLightSlavik
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=6e53b1a2f340d77429d435babcec107c7cc50972&v=4
url: https://github.com/ArcLightSlavik
- login: hard-coders
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=f2d3d2038c55d86d7f9348f4e6c5e30191e4ee8b&v=4
@@ -296,6 +320,14 @@ top_reviewers:
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/13096845?u=646eba44db720e37d0dbe8e98e77ab534ea78a20&v=4
url: https://github.com/PandaHun
- login: bezaca
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4
url: https://github.com/bezaca
- login: lsglucas
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
url: https://github.com/lsglucas
- login: rjNemo
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
@@ -316,22 +348,26 @@ top_reviewers:
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
url: https://github.com/raphaelauv
- login: NastasiaSaby
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/8245071?u=b3afd005f9e4bf080c219ef61a592b3a8004b764&v=4
url: https://github.com/NastasiaSaby
- login: Smlep
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
url: https://github.com/Smlep
- login: jovicon
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/21287303?u=b049eac3e51a4c0473c2efe66b4d28a7d8f2b572&v=4
url: https://github.com/jovicon
- login: NastasiaSaby
- login: Mause
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/8245071?u=b3afd005f9e4bf080c219ef61a592b3a8004b764&v=4
url: https://github.com/NastasiaSaby
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
url: https://github.com/Mause
- login: nimctl
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/49960770?u=e39b11d47188744ee07b2a1c7ce1a1bdf3c80760&v=4
url: https://github.com/nimctl
- login: Mause
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
url: https://github.com/Mause
- login: juntatalor
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/8134632?v=4
@@ -340,6 +376,10 @@ top_reviewers:
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/63564282?u=0078826509dbecb2fdb543f4e881c9cd06157893&v=4
url: https://github.com/SnkSynthesis
- login: anthonycepeda
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=892f700c79f9732211bd5221bf16eec32356a732&v=4
url: https://github.com/anthonycepeda
- login: euri10
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
@@ -356,6 +396,10 @@ top_reviewers:
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/31370133?v=4
url: https://github.com/Zxilly
- login: Bluenix2
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/38372706?u=c9d28aff15958d6ebf1971148bfb3154ff943c4f&v=4
url: https://github.com/Bluenix2
sponsors_50:
- login: johnadjei
avatarUrl: https://avatars.githubusercontent.com/u/767860?v=4
@@ -363,6 +407,9 @@ sponsors_50:
- login: wdwinslow
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4
url: https://github.com/wdwinslow
- login: bingwu-chime
avatarUrl: https://avatars.githubusercontent.com/u/67026650?u=603a6b345f25c20c6706a8a6c7f71ae688d649a5&v=4
url: https://github.com/bingwu-chime
sponsors:
- login: kamalgill
avatarUrl: https://avatars.githubusercontent.com/u/133923?u=0df9181d97436ce330e9acf90ab8a54b7022efe7&v=4
@@ -370,15 +417,15 @@ sponsors:
- login: grillazz
avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=16d7d0ffa5dfb99f8834f8f76d90e138ba09b94a&v=4
url: https://github.com/grillazz
- login: CarlosDomingues
avatarUrl: https://avatars.githubusercontent.com/u/11181378?u=4c15832fa030a5f3fd024ca4912093b4b59a40bd&v=4
url: https://github.com/CarlosDomingues
- login: tizz98
avatarUrl: https://avatars.githubusercontent.com/u/5739698?u=f095a3659e3a8e7c69ccd822696990b521ea25f9&v=4
url: https://github.com/tizz98
- login: jmaralc
avatarUrl: https://avatars.githubusercontent.com/u/21101214?u=b15a9f07b7cbf6c9dcdbcb6550bbd2c52f55aa50&v=4
url: https://github.com/jmaralc
- login: lucone83
avatarUrl: https://avatars.githubusercontent.com/u/2812607?u=49c0c4454d4c98eacdcac0e33c1d83dc6fe5a37f&v=4
url: https://github.com/lucone83
- login: psgandalf
avatarUrl: https://avatars.githubusercontent.com/u/8134158?v=4
url: https://github.com/psgandalf
- login: samuelcolvin
avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=807390ba9cfe23906c3bf8a0d56aaca3cf2bfa0d&v=4
url: https://github.com/samuelcolvin
@@ -394,8 +441,11 @@ sponsors:
- login: falkben
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
url: https://github.com/falkben
- login: jqueguiner
avatarUrl: https://avatars.githubusercontent.com/u/690878?u=e4835b2a985a0f2d52018e4926cb5a58c26a62e8&v=4
url: https://github.com/jqueguiner
- login: Mazyod
avatarUrl: https://avatars.githubusercontent.com/u/860511?u=a76c978bdf91c2b332ab8769935fa415d0a8091b&v=4
avatarUrl: https://avatars.githubusercontent.com/u/860511?v=4
url: https://github.com/Mazyod
- login: ltieman
avatarUrl: https://avatars.githubusercontent.com/u/1084689?u=e69b17de17cb3ca141a17daa7ccbe173ceb1eb17&v=4
@@ -415,9 +465,9 @@ sponsors:
- login: madisonmay
avatarUrl: https://avatars.githubusercontent.com/u/2645393?u=f22b93c6ea345a4d26a90a3834dfc7f0789fcb63&v=4
url: https://github.com/madisonmay
- login: jorgecarleitao
avatarUrl: https://avatars.githubusercontent.com/u/2772607?u=6ba4aa5ded7b492043ba76f3f900e3b4cc102b57&v=4
url: https://github.com/jorgecarleitao
- 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
@@ -430,18 +480,21 @@ sponsors:
- login: dudil
avatarUrl: https://avatars.githubusercontent.com/u/4785835?u=58b7ea39123e0507f3b2996448a27256b16fd697&v=4
url: https://github.com/dudil
- login: p141592
avatarUrl: https://avatars.githubusercontent.com/u/5256328?u=07bc6374282ab3d08511afebaa5d511987d034f1&v=4
url: https://github.com/p141592
- login: ennui93
avatarUrl: https://avatars.githubusercontent.com/u/5300907?u=5b5452725ddb391b2caaebf34e05aba873591c3a&v=4
url: https://github.com/ennui93
- login: sco1
avatarUrl: https://avatars.githubusercontent.com/u/5323929?u=2b8434060d0c9d93de80a2a945baed94a412c31e&v=4
url: https://github.com/sco1
- login: MacroPower
avatarUrl: https://avatars.githubusercontent.com/u/5648814?u=b2730000c9f9a471282b9849d2cc85711d7973d4&v=4
url: https://github.com/MacroPower
- login: ginomempin
avatarUrl: https://avatars.githubusercontent.com/u/6091865?v=4
url: https://github.com/ginomempin
- login: iwpnd
avatarUrl: https://avatars.githubusercontent.com/u/6152183?u=b2286006daafff5f991557344fee20b5da59639a&v=4
url: https://github.com/iwpnd
- login: s3ich4n
avatarUrl: https://avatars.githubusercontent.com/u/6926298?u=ba3025d698e1c986655e776ae383a3d60d9d578e&v=4
url: https://github.com/s3ich4n
@@ -451,9 +504,6 @@ sponsors:
- login: christippett
avatarUrl: https://avatars.githubusercontent.com/u/7218120?u=434b9d29287d7de25772d94ddc74a9bd6d969284&v=4
url: https://github.com/christippett
- login: yukiyan
avatarUrl: https://avatars.githubusercontent.com/u/7304122?u=fadb64baf3934c708349bbea1142d260a6b6ce6b&v=4
url: https://github.com/yukiyan
- login: Kludex
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
url: https://github.com/Kludex
@@ -466,18 +516,12 @@ sponsors:
- login: cristeaadrian
avatarUrl: https://avatars.githubusercontent.com/u/9112724?v=4
url: https://github.com/cristeaadrian
- login: opunsoars
avatarUrl: https://avatars.githubusercontent.com/u/9273060?u=97f5ecec274e159b22787ca2f466f13ab1797758&v=4
url: https://github.com/opunsoars
- login: otivvormes
avatarUrl: https://avatars.githubusercontent.com/u/11317418?u=6de1edefb6afd0108c0ad2816bd6efc4464a9c44&v=4
url: https://github.com/otivvormes
- login: iambobmae
avatarUrl: https://avatars.githubusercontent.com/u/12390270?u=c9a35c2ee5092a9b4135ebb1f91b7f521c467031&v=4
url: https://github.com/iambobmae
- login: Cozmo25
avatarUrl: https://avatars.githubusercontent.com/u/12619962?u=679dcd6785121e14f6254e9dd0961baf3b1fef5d&v=4
url: https://github.com/Cozmo25
- login: ronaldnwilliams
avatarUrl: https://avatars.githubusercontent.com/u/13632749?u=ac41a086d0728bf66a9d2bee9e5e377041ff44a4&v=4
url: https://github.com/ronaldnwilliams
@@ -508,6 +552,9 @@ sponsors:
- login: daddycocoaman
avatarUrl: https://avatars.githubusercontent.com/u/21189155?u=756f6a17c71c538b11470f70839baacab43807ef&v=4
url: https://github.com/daddycocoaman
- login: Filimoa
avatarUrl: https://avatars.githubusercontent.com/u/21352040?u=75e02d102d2ee3e3d793e555fa5c63045913ccb0&v=4
url: https://github.com/Filimoa
- login: raminsj13
avatarUrl: https://avatars.githubusercontent.com/u/24259406?u=d51f2a526312ebba150a06936ed187ca0727d329&v=4
url: https://github.com/raminsj13
@@ -520,9 +567,6 @@ sponsors:
- login: orihomie
avatarUrl: https://avatars.githubusercontent.com/u/29889683?u=6bc2135a52fcb3a49e69e7d50190796618185fda&v=4
url: https://github.com/orihomie
- login: Huffon
avatarUrl: https://avatars.githubusercontent.com/u/31345506?u=c41bdf60facd004ec6364bf718ce16f8da2b884f&v=4
url: https://github.com/Huffon
- login: SaltyCoco
avatarUrl: https://avatars.githubusercontent.com/u/31451104?u=6ee4e17c07d21b7054f54a12fa9cc377a1b24ff9&v=4
url: https://github.com/SaltyCoco
@@ -541,9 +585,6 @@ sponsors:
- login: dudikbender
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=494f85229115076121b3639a3806bbac1c6ae7f6&v=4
url: https://github.com/dudikbender
- login: Brontomerus
avatarUrl: https://avatars.githubusercontent.com/u/61284158?u=4aee24daee1921daa722cde3fcb6701e3e37ea31&v=4
url: https://github.com/Brontomerus
- login: primer-io
avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4
url: https://github.com/primer-io
@@ -556,24 +597,24 @@ sponsors:
- login: anthonycepeda
avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=892f700c79f9732211bd5221bf16eec32356a732&v=4
url: https://github.com/anthonycepeda
- login: pqhaa
avatarUrl: https://avatars.githubusercontent.com/u/81242906?u=a71c5869241fc14dea6e413fb4b84287fefed38e&v=4
url: https://github.com/pqhaa
- login: saldistefano
avatarUrl: https://avatars.githubusercontent.com/u/82109221?v=4
url: https://github.com/saldistefano
- login: linux-china
avatarUrl: https://avatars.githubusercontent.com/u/46711?v=4
url: https://github.com/linux-china
- login: jhb
avatarUrl: https://avatars.githubusercontent.com/u/142217?v=4
url: https://github.com/jhb
- login: yourkin
avatarUrl: https://avatars.githubusercontent.com/u/178984?v=4
url: https://github.com/yourkin
- login: jmagnusson
avatarUrl: https://avatars.githubusercontent.com/u/190835?v=4
url: https://github.com/jmagnusson
- login: slafs
avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4
url: https://github.com/slafs
- login: adamghill
avatarUrl: https://avatars.githubusercontent.com/u/317045?u=f1349d5ffe84a19f324e204777859fbf69ddf633&v=4
url: https://github.com/adamghill
- login: eteq
avatarUrl: https://avatars.githubusercontent.com/u/346587?v=4
url: https://github.com/eteq
@@ -583,15 +624,24 @@ sponsors:
- login: hongqn
avatarUrl: https://avatars.githubusercontent.com/u/405587?u=470b4c04832e45141fd5264d3354845cc9fc6466&v=4
url: https://github.com/hongqn
- login: lukin0110
avatarUrl: https://avatars.githubusercontent.com/u/992275?u=d20b7e18b213ae7004585b382eccb542db5ffe48&v=4
url: https://github.com/lukin0110
- login: rinckd
avatarUrl: https://avatars.githubusercontent.com/u/546002?u=1fcc7e664dc86524a0af6837a0c222829c3fd4e5&v=4
url: https://github.com/rinckd
- login: Pytlicek
avatarUrl: https://avatars.githubusercontent.com/u/1430522?u=169dba3bfbc04ed214a914640ff435969f19ddb3&v=4
url: https://github.com/Pytlicek
- login: okken
avatarUrl: https://avatars.githubusercontent.com/u/1568356?u=0a991a21bdc62e2bea9ad311652f2c45f453dc84&v=4
url: https://github.com/okken
- login: leogregianin
avatarUrl: https://avatars.githubusercontent.com/u/1684053?u=94ddd387601bd1805034dbe83e6eba0491c15323&v=4
url: https://github.com/leogregianin
- login: cbonoz
avatarUrl: https://avatars.githubusercontent.com/u/2351087?u=fd3e8030b2cc9fbfbb54a65e9890c548a016f58b&v=4
url: https://github.com/cbonoz
- login: rglsk
avatarUrl: https://avatars.githubusercontent.com/u/2768101?u=e349c88673f2155fe021331377c656a9d74bcc25&v=4
url: https://github.com/rglsk
- login: Atem18
avatarUrl: https://avatars.githubusercontent.com/u/2875254?v=4
url: https://github.com/Atem18
@@ -602,7 +652,7 @@ sponsors:
avatarUrl: https://avatars.githubusercontent.com/u/3438238?u=c57605077c31a8f7b2341fc4912507f91b4a5621&v=4
url: https://github.com/igorcorrea
- login: zsinx6
avatarUrl: https://avatars.githubusercontent.com/u/3532625?v=4
avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4
url: https://github.com/zsinx6
- login: pawamoy
avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4
@@ -610,9 +660,12 @@ sponsors:
- login: spyker77
avatarUrl: https://avatars.githubusercontent.com/u/4953435?u=568baae6469628e020fe0bab16e395b7ae10c7d3&v=4
url: https://github.com/spyker77
- login: iwpnd
avatarUrl: https://avatars.githubusercontent.com/u/6152183?u=b2286006daafff5f991557344fee20b5da59639a&v=4
url: https://github.com/iwpnd
- login: serfer2
avatarUrl: https://avatars.githubusercontent.com/u/5196592?u=e8798d87120952ed41876778f0cc8a1ddb47f901&v=4
url: https://github.com/serfer2
- login: JonasKs
avatarUrl: https://avatars.githubusercontent.com/u/5310116?u=98a049f3e1491bffb91e1feb7e93def6881a9389&v=4
url: https://github.com/JonasKs
- login: holec
avatarUrl: https://avatars.githubusercontent.com/u/6438041?u=f5af71ec85b3a9d7b8139cb5af0512b02fa9ab1e&v=4
url: https://github.com/holec
@@ -631,45 +684,69 @@ sponsors:
- login: hard-coders
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=f2d3d2038c55d86d7f9348f4e6c5e30191e4ee8b&v=4
url: https://github.com/hard-coders
- login: satwikkansal
avatarUrl: https://avatars.githubusercontent.com/u/10217535?u=b12d6ef74ea297de9e46da6933b1a5b7ba9e6a61&v=4
url: https://github.com/satwikkansal
- login: pheanex
avatarUrl: https://avatars.githubusercontent.com/u/10408624?u=5b6bab6ee174aa6e991333e06eb29f628741013d&v=4
url: https://github.com/pheanex
- login: wotori
avatarUrl: https://avatars.githubusercontent.com/u/10486621?u=0044c295b91694b8c9bccc0a805681f794250f7b&v=4
url: https://github.com/wotori
- login: JimFawkes
avatarUrl: https://avatars.githubusercontent.com/u/12075115?u=dc58ecfd064d72887c34bf500ddfd52592509acd&v=4
url: https://github.com/JimFawkes
- login: logan-connolly
avatarUrl: https://avatars.githubusercontent.com/u/16244943?u=8ae66dfbba936463cc8aa0dd7a6d2b4c0cc757eb&v=4
url: https://github.com/logan-connolly
- login: sebastianmarines
avatarUrl: https://avatars.githubusercontent.com/u/18373185?u=e0be7c230456a2bdc0825e3d6541ea8966e22028&v=4
url: https://github.com/sebastianmarines
- login: Filimoa
avatarUrl: https://avatars.githubusercontent.com/u/21352040?u=75e02d102d2ee3e3d793e555fa5c63045913ccb0&v=4
url: https://github.com/Filimoa
- login: iPr0ger
avatarUrl: https://avatars.githubusercontent.com/u/19322290?v=4
url: https://github.com/iPr0ger
- login: sadikkuzu
avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=765ed469c44c004560079210ccdad5b29938eaa9&v=4
url: https://github.com/sadikkuzu
- login: ghandic
avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4
url: https://github.com/ghandic
- login: MoronVV
avatarUrl: https://avatars.githubusercontent.com/u/24293616?v=4
url: https://github.com/MoronVV
- login: AngusWG
avatarUrl: https://avatars.githubusercontent.com/u/26385612?u=f4d4c8bd2097cdd58eb9e385932b83c78777f3c0&v=4
url: https://github.com/AngusWG
- login: mertguvencli
avatarUrl: https://avatars.githubusercontent.com/u/29762151?u=16a906d90df96c8cff9ea131a575c4bc171b1523&v=4
url: https://github.com/mertguvencli
- login: rgreen32
avatarUrl: https://avatars.githubusercontent.com/u/35779241?u=c9d64ad1ab364b6a1ec8e3d859da9ca802d681d8&v=4
url: https://github.com/rgreen32
- login: leynier
avatarUrl: https://avatars.githubusercontent.com/u/36774373?u=60eee7ab14aada5aab8af6fbd11d14732750a7ab&v=4
url: https://github.com/leynier
- login: askurihin
avatarUrl: https://avatars.githubusercontent.com/u/37978981?v=4
url: https://github.com/askurihin
- login: berrysauce
avatarUrl: https://avatars.githubusercontent.com/u/38889179?u=758ed15a5be8bbd03855f5a74f42c19f7946ee32&v=4
url: https://github.com/berrysauce
- login: JitPackJoyride
avatarUrl: https://avatars.githubusercontent.com/u/40203625?u=9638bfeacfa5940358188f8205ce662bba022b53&v=4
url: https://github.com/JitPackJoyride
- login: es3n1n
avatarUrl: https://avatars.githubusercontent.com/u/40367813?u=f562f0f93b108a923be6aba1ec041128286c3c50&v=4
avatarUrl: https://avatars.githubusercontent.com/u/40367813?u=e881a3880f1e342d19a1ea7c8e1b6d76c52dc294&v=4
url: https://github.com/es3n1n
- login: ilias-ant
avatarUrl: https://avatars.githubusercontent.com/u/42189572?u=064bf3a60fcb3c445ab038386321098920b3f4e4&v=4
avatarUrl: https://avatars.githubusercontent.com/u/42189572?u=a2d6121bac4d125d92ec207460fa3f1842d37e66&v=4
url: https://github.com/ilias-ant
- login: kbhatiya999
avatarUrl: https://avatars.githubusercontent.com/u/47816034?v=4
url: https://github.com/kbhatiya999
- login: akanz1
avatarUrl: https://avatars.githubusercontent.com/u/51492342?u=2280f57134118714645e16b535c1a37adf6b369b&v=4
url: https://github.com/akanz1
- login: rychardvale
avatarUrl: https://avatars.githubusercontent.com/u/54805553?u=3d20ab05301d05f9ac3500fb79a2bfee3842b753&v=4
url: https://github.com/rychardvale
- login: athemeart
avatarUrl: https://avatars.githubusercontent.com/u/61623624?v=4
url: https://github.com/athemeart
- login: Rhythmicc
avatarUrl: https://avatars.githubusercontent.com/u/29839231?u=2100781089a259707c475c4547bd7995b0fc18ee&v=4
url: https://github.com/Rhythmicc

View File

@@ -161,10 +161,33 @@ An alternative JSON response using <a href="https://github.com/ultrajson/ultrajs
Returns an HTTP redirect. Uses a 307 status code (Temporary Redirect) by default.
You can return a `RedirectResponse` directly:
```Python hl_lines="2 9"
{!../../../docs_src/custom_response/tutorial006.py!}
```
---
Or you can use it in the `response_class` parameter:
```Python hl_lines="2 7 9"
{!../../../docs_src/custom_response/tutorial006b.py!}
```
If you do that, then you can return the URL directly from your *path operation* function.
In this case, the `status_code` used will be the default one for the `RedirectResponse`, which is `307`.
---
You can also use the `status_code` parameter combined with the `response_class` parameter:
```Python hl_lines="2 7 9"
{!../../../docs_src/custom_response/tutorial006c.py!}
```
### `StreamingResponse`
Takes an async generator or a normal generator/iterator and streams the response body.
@@ -203,6 +226,14 @@ File responses will include appropriate `Content-Length`, `Last-Modified` and `E
{!../../../docs_src/custom_response/tutorial009.py!}
```
You can also use the `response_class` parameter:
```Python hl_lines="2 8 10"
{!../../../docs_src/custom_response/tutorial009b.py!}
```
In this case, you can return the file path directly from your *path operation* function.
## Default response class
When creating a **FastAPI** class instance or an `APIRouter` you can specify which response class to use by default.

View File

@@ -3,6 +3,55 @@
## Latest Changes
## 0.66.0
### Features
* ✨ Allow setting the `response_class` to `RedirectResponse` and returning the URL from the function. New and updated docs are in the tutorial section **Custom Response - HTML, Stream, File, others**, in [RedirectResponse](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse) and in [FileResponse](https://fastapi.tiangolo.com/advanced/custom-response/#fileresponse). PR [#3457](https://github.com/tiangolo/fastapi/pull/3457) by [@tiangolo](https://github.com/tiangolo).
### Fixes
* 🐛 Fix include/exclude for dicts in `jsonable_encoder`. PR [#2016](https://github.com/tiangolo/fastapi/pull/2016) by [@Rubikoid](https://github.com/Rubikoid).
* 🐛 Support custom OpenAPI / JSON Schema fields in the generated output OpenAPI. PR [#1429](https://github.com/tiangolo/fastapi/pull/1429) by [@jmagnusson](https://github.com/jmagnusson).
### Translations
* 🌐 Add Spanish translation for `tutorial/query-params.md`. PR [#2243](https://github.com/tiangolo/fastapi/pull/2243) by [@mariacamilagl](https://github.com/mariacamilagl).
* 🌐 Add Spanish translation for `advanced/response-directly.md`. PR [#1253](https://github.com/tiangolo/fastapi/pull/1253) by [@jfunez](https://github.com/jfunez).
* 🌐 Add Spanish translation for `advanced/additional-status-codes.md`. PR [#1252](https://github.com/tiangolo/fastapi/pull/1252) by [@jfunez](https://github.com/jfunez).
* 🌐 Add Spanish translation for `advanced/path-operation-advanced-configuration.md`. PR [#1251](https://github.com/tiangolo/fastapi/pull/1251) by [@jfunez](https://github.com/jfunez).
## 0.65.3
### Fixes
* ♻ Assume request bodies contain JSON when no Content-Type header is provided. This fixes a breaking change introduced by [0.65.2 with PR #2118](https://github.com/tiangolo/fastapi/pull/2118). It should allow upgrading FastAPI applications with clients that send JSON data without a `Content-Type` header. And there's still protection against CSRFs. PR [#3456](https://github.com/tiangolo/fastapi/pull/3456) by [@tiangolo](https://github.com/tiangolo).
### Translations
* 🌐 Initialize Indonesian translations. PR [#3014](https://github.com/tiangolo/fastapi/pull/3014) by [@pace-noge](https://github.com/pace-noge).
* 🌐 Add Spanish translation of Tutorial - Path Parameters. PR [#2219](https://github.com/tiangolo/fastapi/pull/2219) by [@mariacamilagl](https://github.com/mariacamilagl).
* 🌐 Add Spanish translation of Tutorial - First Steps. PR [#2208](https://github.com/tiangolo/fastapi/pull/2208) by [@mariacamilagl](https://github.com/mariacamilagl).
* 🌐 Portuguese translation of Tutorial - Body - Fields. PR [#3420](https://github.com/tiangolo/fastapi/pull/3420) by [@ComicShrimp](https://github.com/ComicShrimp).
* 🌐 Add Chinese translation for Tutorial - Request - Forms - and - Files. PR [#3249](https://github.com/tiangolo/fastapi/pull/3249) by [@jaystone776](https://github.com/jaystone776).
* 🌐 Add Chinese translation for Tutorial - Handling - Errors. PR [#3299](https://github.com/tiangolo/fastapi/pull/3299) by [@jaystone776](https://github.com/jaystone776).
* 🌐 Add Chinese translation for Tutorial - Form - Data. PR [#3248](https://github.com/tiangolo/fastapi/pull/3248) by [@jaystone776](https://github.com/jaystone776).
* 🌐 Add Chinese translation for Tutorial - Body - Updates. PR [#3237](https://github.com/tiangolo/fastapi/pull/3237) by [@jaystone776](https://github.com/jaystone776).
* 🌐 Add Chinese translation for FastAPI People. PR [#3112](https://github.com/tiangolo/fastapi/pull/3112) by [@hareru](https://github.com/hareru).
* 🌐 Add French translation for Project Generation. PR [#3197](https://github.com/tiangolo/fastapi/pull/3197) by [@Smlep](https://github.com/Smlep).
* 🌐 Add French translation for Python Types Intro. PR [#3185](https://github.com/tiangolo/fastapi/pull/3185) by [@Smlep](https://github.com/Smlep).
* 🌐 Add French translation for External Links. PR [#3103](https://github.com/tiangolo/fastapi/pull/3103) by [@Smlep](https://github.com/Smlep).
* 🌐 Add French translation for Alternatives, Inspiration and Comparisons. PR [#3020](https://github.com/tiangolo/fastapi/pull/3020) by [@rjNemo](https://github.com/rjNemo).
* 🌐 Fix Chinese translation code snippet mismatch in Tutorial - Python Types Intro. PR [#2573](https://github.com/tiangolo/fastapi/pull/2573) by [@BoYanZh](https://github.com/BoYanZh).
* 🌐 Add Portuguese translation for Development Contributing. PR [#1364](https://github.com/tiangolo/fastapi/pull/1364) by [@Serrones](https://github.com/Serrones).
* 🌐 Add Chinese translation for Tutorial - Request - Files. PR [#3244](https://github.com/tiangolo/fastapi/pull/3244) by [@jaystone776](https://github.com/jaystone776).
### Internal
* 👥 Update FastAPI People. PR [#3450](https://github.com/tiangolo/fastapi/pull/3450) by [@github-actions[bot]](https://github.com/apps/github-actions).
* 👥 Update FastAPI People. PR [#3319](https://github.com/tiangolo/fastapi/pull/3319) by [@github-actions[bot]](https://github.com/apps/github-actions).
* ⬆ Upgrade docs development dependency on `typer-cli` to >=0.0.12 to fix conflicts. PR [#3429](https://github.com/tiangolo/fastapi/pull/3429) by [@tiangolo](https://github.com/tiangolo).
## 0.65.2
### Security fixes

View File

@@ -41,6 +41,7 @@ nav:
- en: /
- es: /es/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
@@ -193,6 +194,8 @@ extra:
name: es - español
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/

View File

@@ -0,0 +1,37 @@
# Códigos de estado adicionales
Por defecto, **FastAPI** devolverá las respuestas utilizando una `JSONResponse`, poniendo el contenido que devuelves en tu *operación de path* dentro de esa `JSONResponse`.
Utilizará el código de estado por defecto, o el que hayas asignado en tu *operación de path*.
## Códigos de estado adicionales
Si quieres devolver códigos de estado adicionales además del principal, puedes hacerlo devolviendo directamente una `Response`, como una `JSONResponse`, y asignar directamente el código de estado adicional.
Por ejemplo, digamos que quieres tener una *operación de path* que permita actualizar ítems y devolver códigos de estado HTTP 200 "OK" cuando sea exitosa.
Pero también quieres que acepte nuevos ítems. Cuando los ítems no existan anteriormente, serán creados y devolverá un código de estado HTTP 201 "Created".
Para conseguir esto importa `JSONResponse` y devuelve ahí directamente tu contenido, asignando el `status_code` que quieras:
```Python hl_lines="2 19"
{!../../../docs_src/additional_status_codes/tutorial001.py!}
```
!!! warning "Advertencia"
Cuando devuelves directamente una `Response`, como en los ejemplos anteriores, será devuelta directamente.
No será serializado con el modelo, etc.
Asegurate de que la respuesta tenga los datos que quieras, y que los valores sean JSON válidos (si estás usando `JSONResponse`).
!!! note "Detalles Técnicos"
También podrías utilizar `from starlette.responses import JSONResponse`.
**FastAPI** provee las mismas `starlette.responses` que `fastapi.responses` simplemente como una convención para ti, el desarrollador. Pero la mayoría de las respuestas disponibles vienen directamente de Starlette. Lo mismo con `status`.
## OpenAPI y documentación de API
Si quieres devolver códigos de estado y respuestas adicionales directamente, estas no estarán incluidas en el schema de OpenAPI (documentación de API), porque FastAPI no tiene una manera de conocer de antemano lo que vas a devolver.
Pero puedes documentar eso en tu código usando [Respuestas Adicionales](additional-responses.md){.internal-link target=_blank}.

View File

@@ -0,0 +1,52 @@
# Configuración avanzada de las operaciones de path
## OpenAPI operationId
!!! warning "Advertencia"
Si no eres una persona "experta" en OpenAPI, probablemente no necesitas leer esto.
Puedes asignar el `operationId` de OpenAPI para ser usado en tu *operación de path* con el parámetro `operation_id`.
En este caso tendrías que asegurarte de que sea único para cada operación.
```Python hl_lines="6"
{!../../../docs_src/path_operation_advanced_configuration/tutorial001.py!}
```
### Usando el nombre de la *función de la operación de path* en el operationId
Si quieres usar tus nombres de funciones de API como `operationId`s, puedes iterar sobre todos ellos y sobrescribir `operation_id` de cada *operación de path* usando su `APIRoute.name`.
Deberías hacerlo después de adicionar todas tus *operaciones de path*.
```Python hl_lines="2 12 13 14 15 16 17 18 19 20 21 24"
{!../../../docs_src/path_operation_advanced_configuration/tutorial002.py!}
```
!!! tip "Consejo"
Si llamas manualmente a `app.openapi()`, debes actualizar el `operationId`s antes de hacerlo.
!!! warning "Advertencia"
Si haces esto, debes asegurarte de que cada una de tus *funciones de las operaciones de path* tenga un nombre único.
Incluso si están en diferentes módulos (archivos Python).
## Excluir de OpenAPI
Para excluir una *operación de path* del esquema OpenAPI generado (y por tanto del la documentación generada automáticamente), usa el parámetro `include_in_schema` y asigna el valor como `False`;
```Python hl_lines="6"
{!../../../docs_src/path_operation_advanced_configuration/tutorial003.py!}
```
## Descripción avanzada desde el docstring
Puedes limitar las líneas usadas desde el docstring de una *operación de path* para OpenAPI.
Agregar un `\f` (un carácter de "form feed" escapado) hace que **FastAPI** trunque el output utilizada para OpenAPI en ese punto.
No será mostrado en la documentación, pero otras herramientas (como Sphinx) serán capaces de usar el resto.
```Python hl_lines="19 20 21 22 23 24 25 26 27 28 29"
{!../../../docs_src/path_operation_advanced_configuration/tutorial004.py!}
```

View File

@@ -0,0 +1,63 @@
# Devolver una respuesta directamente
Cuando creas una *operación de path* normalmente puedes devolver cualquier dato: un `dict`, una `list`, un modelo Pydantic, un modelo de base de datos, etc.
Por defecto, **FastAPI** convertiría automáticamente ese valor devuelto a JSON usando el `jsonable_encoder` explicado en [Codificador Compatible JSON](../tutorial/encoder.md){.internal-link target=_blank}.
Luego, tras bastidores, pondría esos datos compatibles con JSON (por ejemplo, un `dict`) dentro de una `JSONResponse` que se usaría para enviar la respuesta al cliente.
Pero puedes devolver una `JSONResponse` directamente de tu *operación de path*.
Esto puede ser útil, por ejemplo, para devolver cookies o headers personalizados.
## Devolver una `Response`
De hecho, puedes devolver cualquier `Response` o cualquier subclase de la misma.
!!! tip "Consejo"
`JSONResponse` en sí misma es una subclase de `Response`.
Y cuando devuelves una `Response`, **FastAPI** la pasará directamente.
No hará ninguna conversión de datos con modelos Pydantic, no convertirá el contenido a ningún tipo, etc.
Esto te da mucha flexibilidad. Puedes devolver cualquier tipo de dato, sobrescribir cualquer declaración de datos o validación, etc.
## Usando el `jsonable_encoder` en una `Response`
Como **FastAPI** no realiza ningún cambio en la `Response` que devuelves, debes asegurarte de que el contenido está listo.
Por ejemplo, no puedes poner un modelo Pydantic en una `JSONResponse` sin primero convertirlo a un `dict` con todos los tipos de datos (como `datetime`, `UUID`, etc) convertidos a tipos compatibles con JSON.
Para esos casos, puedes usar el `jsonable_encoder` para convertir tus datos antes de pasarlos a la respuesta:
```Python hl_lines="4 6 20 21"
{!../../../docs_src/response_directly/tutorial001.py!}
```
!!! note "Detalles Técnicos"
También puedes usar `from starlette.responses import JSONResponse`.
**FastAPI** provee `starlette.responses` como `fastapi.responses`, simplemente como una conveniencia para ti, el desarrollador. Pero la mayoría de las respuestas disponibles vienen directamente de Starlette.
## Devolviendo una `Response` personalizada
El ejemplo anterior muestra las partes que necesitas, pero no es muy útil todavía, dado que podrías simplemente devolver el `item` directamente, y **FastAPI** lo pondría en una `JSONResponse` por ti, convirtiéndolo en un `dict`, etc. Todo esto por defecto.
Ahora, veamos cómo puedes usarlo para devolver una respuesta personalizada.
Digamos que quieres devolver una respuesta <a href="https://en.wikipedia.org/wiki/XML" class="external-link" target="_blank">XML</a>.
Podrías poner tu contenido XML en un string, ponerlo en una `Response` y devolverlo:
```Python hl_lines="1 18"
{!../../../docs_src/response_directly/tutorial002.py!}
```
## Notas
Cuando devuelves una `Response` directamente, los datos no son validados, convertidos (serializados), ni documentados automáticamente.
Pero todavía es posible documentarlo como es descrito en [Respuestas adicionales en OpenAPI](additional-responses.md){.internal-link target=_blank}.
Puedes ver en secciones posteriores como usar/declarar esas `Response`s personalizadas aún teniendo conversión automática de datos, documentación, etc.

View File

@@ -0,0 +1,333 @@
# Primeros pasos
Un archivo muy simple de FastAPI podría verse así:
```Python
{!../../../docs_src/first_steps/tutorial001.py!}
```
Copia eso a un archivo `main.py`.
Corre el servidor en vivo:
<div class="termy">
```console
$ uvicorn main:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
<span style="color: green;">INFO</span>: Started reloader process [28720]
<span style="color: green;">INFO</span>: Started server process [28722]
<span style="color: green;">INFO</span>: Waiting for application startup.
<span style="color: green;">INFO</span>: Application startup complete.
```
</div>
!!! note "Nota"
El comando `uvicorn main:app` se refiere a:
* `main`: el archivo `main.py` (el "módulo" de Python).
* `app`: el objeto creado dentro de `main.py` con la línea `app = FastAPI()`.
* `--reload`: hace que el servidor se reinicie cada vez que cambia el código. Úsalo únicamente para desarrollo.
En el output, hay una línea que dice más o menos:
```hl_lines="4"
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
Esa línea muestra la URL dónde se está sirviendo tu app en tu maquina local.
### Revísalo
Abre tu navegador en <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>.
Verás la respuesta en JSON:
```JSON
{"message": "Hello World"}
```
### Documentación interactiva de la API
Ahora dirígete a <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Ahí verás la documentación automática e interactiva de la API (proveída por <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Documentación alternativa de la API
Ahora, dirígete a <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
Aquí verás la documentación automática alternativa (proveída por <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
### OpenAPI
**FastAPI** genera un "schema" con toda tu API usando el estándar para definir APIs, **OpenAPI**.
#### "Schema"
Un "schema" es una definición o descripción de algo. No es el código que la implementa, sino solo una descripción abstracta.
#### "Schema" de la API
En este caso, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> es una especificación que dicta como se debe definir el schema de tu API.
La definición del schema incluye los paths de tu API, los parámetros que podría recibir, etc.
#### "Schema" de datos
El concepto "schema" también se puede referir a la forma de algunos datos, como un contenido en formato JSON.
En ese caso haría referencia a los atributos del JSON, los tipos de datos que tiene, etc.
#### OpenAPI y JSON Schema
OpenAPI define un schema de API para tu API. Ese schema incluye definiciones (o "schemas") de los datos enviados y recibidos por tu API usando **JSON Schema**, el estándar para los schemas de datos en JSON.
#### Revisa el `openapi.json`
Si sientes curiosidad por saber cómo se ve el schema de OpenAPI en bruto, FastAPI genera automáticamente un (schema) JSON con la descripción de todo tu API.
Lo puedes ver directamente en: <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
Esto te mostrará un JSON que comienza con algo como:
```JSON
{
"openapi": "3.0.2",
"info": {
"title": "FastAPI",
"version": "0.1.0"
},
"paths": {
"/items/": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
...
```
#### ¿Para qué se usa OpenAPI?
El schema de OpenAPI es lo que alimenta a los dos sistemas de documentación interactiva incluidos.
También hay docenas de alternativas, todas basadas en OpenAPI. Podrías añadir fácilmente cualquiera de esas alternativas a tu aplicación construida con **FastAPI**.
También podrías usarlo para generar código automáticamente, para los clientes que se comunican con tu API. Por ejemplo, frontend, móvil o aplicaciones de IoT.
## Repaso, paso a paso
### Paso 1: importa `FastAPI`
```Python hl_lines="1"
{!../../../docs_src/first_steps/tutorial001.py!}
```
`FastAPI` es una clase de Python que provee toda la funcionalidad para tu API.
!!! note "Detalles Técnicos"
`FastAPI` es una clase que hereda directamente de `Starlette`.
También puedes usar toda la funcionalidad de <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>.
### Paso 2: crea un "instance" de `FastAPI`
```Python hl_lines="3"
{!../../../docs_src/first_steps/tutorial001.py!}
```
Aquí la variable `app` será un instance de la clase `FastAPI`.
Este será el punto de interacción principal para crear todo tu API.
Esta `app` es la misma a la que nos referimos cuando usamos el comando de `uvicorn`:
<div class="termy">
```console
$ uvicorn main:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
Si creas un app como:
```Python hl_lines="3"
{!../../../docs_src/first_steps/tutorial002.py!}
```
y lo guardas en un archivo `main.py`, entonces ejecutarías `uvicorn` así:
<div class="termy">
```console
$ uvicorn main:my_awesome_api --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
### Paso 3: crea un *operación de path*
#### Path
"Path" aquí se refiere a la última parte de una URL comenzando desde el primer `/`.
Entonces, en una URL como:
```
https://example.com/items/foo
```
...el path sería:
```
/items/foo
```
!!! info "Información"
Un "path" también se conoce habitualmente como "endpoint", "route" o "ruta".
Cuando construyes una API, el "path" es la manera principal de separar los <abbr title="en inglés: separation of concerns">"intereses"</abbr> y los "recursos".
#### Operación
"Operación" aquí se refiere a uno de los "métodos" de HTTP.
Uno como:
* `POST`
* `GET`
* `PUT`
* `DELETE`
...y los más exóticos:
* `OPTIONS`
* `HEAD`
* `PATCH`
* `TRACE`
En el protocolo de HTTP, te puedes comunicar con cada path usando uno (o más) de estos "métodos".
---
Cuando construyes APIs, normalmente usas uno de estos métodos específicos de HTTP para realizar una acción específica.
Normalmente usas:
* `POST`: para crear datos.
* `GET`: para leer datos.
* `PUT`: para actualizar datos.
* `DELETE`: para borrar datos.
Así que en OpenAPI, cada uno de estos métodos de HTTP es referido como una "operación".
Nosotros también los llamaremos "**operación**".
#### Define un *decorador de operaciones de path*
```Python hl_lines="6"
{!../../../docs_src/first_steps/tutorial001.py!}
```
El `@app.get("/")` le dice a **FastAPI** que la función que tiene justo debajo está a cargo de manejar los requests que van a:
* el path `/`
* usando una <abbr title="an HTTP GET method">operación <code>get</code></abbr>
!!! info "Información sobre `@decorator`"
Esa sintaxis `@algo` se llama un "decorador" en Python.
Lo pones encima de una función. Es como un lindo sombrero decorado (creo que de ahí salió el concepto).
Un "decorador" toma la función que tiene debajo y hace algo con ella.
En nuestro caso, este decorador le dice a **FastAPI** que la función que está debajo corresponde al **path** `/` con una **operación** `get`.
Es el "**decorador de operaciones de path**".
También puedes usar las otras operaciones:
* `@app.post()`
* `@app.put()`
* `@app.delete()`
y las más exóticas:
* `@app.options()`
* `@app.head()`
* `@app.patch()`
* `@app.trace()`
!!! tip "Consejo"
Tienes la libertad de usar cada operación (método de HTTP) como quieras.
**FastAPI** no impone ningún significado específico.
La información que está presentada aquí es una guía, no un requerimiento.
Por ejemplo, cuando usas GraphQL normalmente realizas todas las acciones usando únicamente operaciones `POST`.
### Paso 4: define la **función de la operación de path**
Esta es nuestra "**función de la operación de path**":
* **path**: es `/`.
* **operación**: es `get`.
* **función**: es la función debajo del "decorador" (debajo de `@app.get("/")`).
```Python hl_lines="7"
{!../../../docs_src/first_steps/tutorial001.py!}
```
Esto es una función de Python.
Esta función será llamada por **FastAPI** cada vez que reciba un request en la URL "`/`" usando una operación `GET`.
En este caso es una función `async`.
---
También podrías definirla como una función normal, en vez de `async def`:
```Python hl_lines="7"
{!../../../docs_src/first_steps/tutorial003.py!}
```
!!! note "Nota"
Si no sabes la diferencia, revisa el [Async: *"¿Tienes prisa?"*](../async.md#in-a-hurry){.internal-link target=_blank}.
### Paso 5: devuelve el contenido
```Python hl_lines="8"
{!../../../docs_src/first_steps/tutorial001.py!}
```
Puedes devolver `dict`, `list`, valores singulares como un `str`, `int`, etc.
También puedes devolver modelos de Pydantic (ya verás más sobre esto más adelante).
Hay muchos objetos y modelos que pueden ser convertidos automáticamente a JSON (incluyendo ORMs, etc.). Intenta usar tus favoritos, es muy probable que ya tengan soporte.
## Repaso
* Importa `FastAPI`.
* Crea un instance de `app`.
* Escribe un **decorador de operación de path** (como `@app.get("/")`).
* Escribe una **función de la operación de path** (como `def root(): ...` arriba).
* Corre el servidor de desarrollo (como `uvicorn main:app --reload`).

View File

@@ -0,0 +1,244 @@
# Parámetros de path
Puedes declarar los "parámetros" o "variables" con la misma sintaxis que usan los format strings de Python:
```Python hl_lines="6-7"
{!../../../docs_src/path_params/tutorial001.py!}
```
El valor del parámetro de path `item_id` será pasado a tu función como el argumento `item_id`.
Entonces, si corres este ejemplo y vas a <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, verás una respuesta de:
```JSON
{"item_id":"foo"}
```
## Parámetros de path con tipos
Puedes declarar el tipo de un parámetro de path en la función usando las anotaciones de tipos estándar de Python:
```Python hl_lines="7"
{!../../../docs_src/path_params/tutorial002.py!}
```
En este caso, `item_id` es declarado como un `int`.
!!! check "Revisa"
Esto te dará soporte en el editor dentro de tu función, con chequeos de errores, autocompletado, etc.
## <abbr title="también conocido en inglés como: serialization, parsing, marshalling">Conversión</abbr> de datos
Si corres este ejemplo y abres tu navegador en <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a> verás una respuesta de:
```JSON
{"item_id":3}
```
!!! check "Revisa"
Observa que el valor que recibió (y devolvió) tu función es `3`, como un Python `int`, y no un string `"3"`.
Entonces, con esa declaración de tipos **FastAPI** te da <abbr title="convertir el string que viene de un HTTP request a datos de Python">"parsing"</abbr> automático del request.
## Validación de datos
Pero si abres tu navegador en <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a> verás este lindo error de HTTP:
```JSON
{
"detail": [
{
"loc": [
"path",
"item_id"
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
```
debido a que el parámetro de path `item_id` tenía el valor `"foo"`, que no es un `int`.
El mismo error aparecería si pasaras un `float` en vez de un `int` como en: <a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a>
!!! check "Revisa"
Así, con la misma declaración de tipo de Python, **FastAPI** te da validación de datos.
Observa que el error también muestra claramente el punto exacto en el que no pasó la validación.
Esto es increíblemente útil cuando estás desarrollando y debugging código que interactúa con tu API.
## Documentación
Cuando abras tu navegador en <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> verás la documentación automática e interactiva del API como:
<img src="/img/tutorial/path-params/image01.png">
!!! check "Revisa"
Nuevamente, con la misma declaración de tipo de Python, **FastAPI** te da documentación automática e interactiva (integrándose con Swagger UI)
Observa que el parámetro de path está declarado como un integer.
## Beneficios basados en estándares, documentación alternativa
Debido a que el schema generado es del estándar <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md" class="external-link" target="_blank">OpenAPI</a> hay muchas herramientas compatibles.
Es por esto que **FastAPI** mismo provee una documentación alternativa de la API (usando ReDoc), a la que puedes acceder en <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>:
<img src="/img/tutorial/path-params/image02.png">
De la misma manera hay muchas herramientas compatibles. Incluyendo herramientas de generación de código para muchos lenguajes.
## Pydantic
Toda la validación de datos es realizada tras bastidores por <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a>, así que obtienes todos sus beneficios. Así sabes que estás en buenas manos.
Puedes usar las mismas declaraciones de tipos con `str`, `float`, `bool` y otros tipos de datos más complejos.
Exploraremos varios de estos tipos en los próximos capítulos del tutorial.
## El orden importa
Cuando creas *operaciones de path* puedes encontrarte con situaciones en las que tengas un path fijo.
Digamos algo como `/users/me` que sea para obtener datos del usuario actual.
... y luego puedes tener el path `/users/{user_id}` para obtener los datos sobre un usuario específico asociados a un ID de usuario.
Porque las *operaciones de path* son evaluadas en orden, tienes que asegurarte de que el path para `/users/me` sea declarado antes que el path para `/users/{user_id}`:
```Python hl_lines="6 11"
{!../../../docs_src/path_params/tutorial003.py!}
```
De otra manera el path para `/users/{user_id}` coincidiría también con `/users/me` "pensando" que está recibiendo el parámetro `user_id` con el valor `"me"`.
## Valores predefinidos
Si tienes una *operación de path* que recibe un *parámetro de path* pero quieres que los valores posibles del *parámetro de path* sean predefinidos puedes usar un <abbr title="Enumeration">`Enum`</abbr> estándar de Python.
### Crea una clase `Enum`
Importa `Enum` y crea una sub-clase que herede desde `str` y desde `Enum`.
Al heredar desde `str` la documentación de la API podrá saber que los valores deben ser de tipo `string` y podrá mostrarlos correctamente.
Luego crea atributos de clase con valores fijos, que serán los valores disponibles válidos:
```Python hl_lines="1 6-9"
{!../../../docs_src/path_params/tutorial005.py!}
```
!!! info "Información"
Las <a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">Enumerations (o enums) están disponibles en Python</a> desde la versión 3.4.
!!! tip "Consejo"
Si lo estás dudando, "AlexNet", "ResNet", y "LeNet" son solo nombres de <abbr title="Tecnicamente, arquitecturas de modelos de Deep Learning">modelos</abbr> de Machine Learning.
### Declara un *parámetro de path*
Luego, crea un *parámetro de path* con anotaciones de tipos usando la clase enum que creaste (`ModelName`):
```Python hl_lines="16"
{!../../../docs_src/path_params/tutorial005.py!}
```
### Revisa la documentación
Debido a que los valores disponibles para el *parámetro de path* están predefinidos, la documentación interactiva los puede mostrar bien:
<img src="/img/tutorial/path-params/image03.png">
### Trabajando con los *enumerations* de Python
El valor del *parámetro de path* será un *enumeration member*.
#### Compara *enumeration members*
Puedes compararlo con el *enumeration member* en el enum (`ModelName`) que creaste:
```Python hl_lines="17"
{!../../../docs_src/path_params/tutorial005.py!}
```
#### Obtén el *enumeration value*
Puedes obtener el valor exacto (un `str` en este caso) usando `model_name.value`, o en general, `your_enum_member.value`:
```Python hl_lines="20"
{!../../../docs_src/path_params/tutorial005.py!}
```
!!! tip "Consejo"
También podrías obtener el valor `"lenet"` con `ModelName.lenet.value`.
#### Devuelve *enumeration members*
Puedes devolver *enum members* desde tu *operación de path* inclusive en un body de JSON anidado (por ejemplo, un `dict`).
Ellos serán convertidos a sus valores correspondientes (strings en este caso) antes de devolverlos al cliente:
```Python hl_lines="18 21 23"
{!../../../docs_src/path_params/tutorial005.py!}
```
En tu cliente obtendrás una respuesta en JSON como:
```JSON
{
"model_name": "alexnet",
"message": "Deep Learning FTW!"
}
```
## Parámetros de path parameters que contienen paths
Digamos que tienes una *operación de path* con un path `/files/{file_path}`.
Pero necesitas que el mismo `file_path` contenga un path como `home/johndoe/myfile.txt`.
Entonces, la URL para ese archivo sería algo como: `/files/home/johndoe/myfile.txt`.
### Soporte de OpenAPI
OpenAPI no soporta una manera de declarar un *parámetro de path* que contenga un path, dado que esto podría llevar a escenarios que son difíciles de probar y definir.
Sin embargo, lo puedes hacer en **FastAPI** usando una de las herramientas internas de Starlette.
La documentación seguirá funcionando, aunque no añadirá ninguna información diciendo que el parámetro debería contener un path.
### Convertidor de path
Usando una opción directamente desde Starlette puedes declarar un *parámetro de path* que contenga un path usando una URL como:
```
/files/{file_path:path}
```
En este caso el nombre del parámetro es `file_path` y la última parte, `:path`, le dice que el parámetro debería coincidir con cualquier path.
Entonces lo puedes usar con:
```Python hl_lines="6"
{!../../../docs_src/path_params/tutorial004.py!}
```
!!! tip "Consejo"
Podrías necesitar que el parámetro contenga `/home/johndoe/myfile.txt` con un slash inicial (`/`).
En este caso la URL sería `/files//home/johndoe/myfile.txt` con un slash doble (`//`) entre `files` y `home`.
## Repaso
Con **FastAPI**, usando declaraciones de tipo de Python intuitivas y estándares, obtienes:
* Soporte en el editor: chequeos de errores, auto-completado, etc.
* "<abbr title="convertir el string que viene de un HTTP request a datos de Python">Parsing</abbr>" de datos
* Validación de datos
* Anotación de la API y documentación automática
Solo tienes que declararlos una vez.
Esa es probablemente la principal ventaja visible de **FastAPI** sobre otros frameworks alternativos (aparte del rendimiento puro).

View File

@@ -0,0 +1,197 @@
# Parámetros de query
Cuando declaras otros parámetros de la función que no hacen parte de los parámetros de path estos se interpretan automáticamente como parámetros de "query".
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial001.py!}
```
El query es el conjunto de pares de key-value que van después del `?` en la URL, separados por caracteres `&`.
Por ejemplo, en la URL:
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
...los parámetros de query son:
* `skip`: con un valor de `0`
* `limit`: con un valor de `10`
Dado que son parte de la URL son strings "naturalmente".
Pero cuando los declaras con tipos de Python (en el ejemplo arriba, como `int`) son convertidos a ese tipo y son validados con él.
Todo el proceso que aplicaba a los parámetros de path también aplica a los parámetros de query:
* Soporte del editor (obviamente)
* <abbr title="convertir el string que viene de un HTTP request a datos de Python">"Parsing"</abbr> de datos
* Validación de datos
* Documentación automática
## Configuraciones por defecto
Como los parámetros de query no están fijos en una parte del path pueden ser opcionales y pueden tener valores por defecto.
El ejemplo arriba tiene `skip=0` y `limit=10` como los valores por defecto.
Entonces, si vas a la URL:
```
http://127.0.0.1:8000/items/
```
Sería lo mismo que ir a:
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
Pero, si por ejemplo vas a:
```
http://127.0.0.1:8000/items/?skip=20
```
Los valores de los parámetros en tu función serán:
* `skip=20`: porque lo definiste en la URL
* `limit=10`: porque era el valor por defecto
## Parámetros opcionales
Del mismo modo puedes declarar parámetros de query opcionales definiendo el valor por defecto como `None`:
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial002.py!}
```
En este caso el parámetro de la función `q` será opcional y será `None` por defecto.
!!! check "Revisa"
También puedes notar que **FastAPI** es lo suficientemente inteligente para darse cuenta de que el parámetro de path `item_id` es un parámetro de path y que `q` no lo es, y por lo tanto es un parámetro de query.
!!! note "Nota"
FastAPI sabrá que `q` es opcional por el `= None`.
El `Optional` en `Optional[str]` no es usado por FastAPI (FastAPI solo usará la parte `str`), pero el `Optional[str]` le permitirá a tu editor ayudarte a encontrar errores en tu código.
## Conversión de tipos de parámetros de query
También puedes declarar tipos `bool` y serán convertidos:
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial003.py!}
```
En este caso, si vas a:
```
http://127.0.0.1:8000/items/foo?short=1
```
o
```
http://127.0.0.1:8000/items/foo?short=True
```
o
```
http://127.0.0.1:8000/items/foo?short=true
```
o
```
http://127.0.0.1:8000/items/foo?short=on
```
o
```
http://127.0.0.1:8000/items/foo?short=yes
```
o cualquier otra variación (mayúsculas, primera letra en mayúscula, etc.) tu función verá el parámetro `short` con un valor `bool` de `True`. Si no, lo verá como `False`.
## Múltiples parámetros de path y query
Puedes declarar múltiples parámetros de path y parámetros de query al mismo tiempo. **FastAPI** sabe cuál es cuál.
No los tienes que declarar en un orden específico.
Serán detectados por nombre:
```Python hl_lines="8 10"
{!../../../docs_src/query_params/tutorial004.py!}
```
## Parámetros de query requeridos
Cuando declaras un valor por defecto para los parámetros que no son de path (por ahora solo hemos visto parámetros de query), entonces no es requerido.
Si no quieres añadir un valor específico sino solo hacerlo opcional, pon el valor por defecto como `None`.
Pero cuando quieres hacer que un parámetro de query sea requerido, puedes simplemente no declararle un valor por defecto:
```Python hl_lines="6-7"
{!../../../docs_src/query_params/tutorial005.py!}
```
Aquí el parámetro de query `needy` es un parámetro de query requerido, del tipo `str`.
Si abres tu navegador en una URL como:
```
http://127.0.0.1:8000/items/foo-item
```
...sin añadir el parámetro `needy` requerido, verás un error como:
```JSON
{
"detail": [
{
"loc": [
"query",
"needy"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}
```
Dado que `needy` es un parámetro requerido necesitarías declararlo en la URL:
```
http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
```
...esto funcionaría:
```JSON
{
"item_id": "foo-item",
"needy": "sooooneedy"
}
```
Por supuesto que también puedes definir algunos parámetros como requeridos, con un valor por defecto y otros completamente opcionales:
```Python hl_lines="10"
{!../../../docs_src/query_params/tutorial006.py!}
```
En este caso hay 3 parámetros de query:
* `needy`, un `str` requerido.
* `skip`, un `int` con un valor por defecto de `0`.
* `limit`, un `int` opcional.
!!! tip "Consejo"
También podrías usar los `Enum`s de la misma manera que con los [Parámetros de path](path-params.md#predefined-values){.internal-link target=_blank}.

View File

@@ -41,6 +41,7 @@ nav:
- en: /
- es: /es/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
@@ -55,6 +56,9 @@ nav:
- python-types.md
- Tutorial - Guía de Usuario:
- tutorial/index.md
- tutorial/first-steps.md
- tutorial/path-params.md
- tutorial/query-params.md
- Guía de Usuario Avanzada:
- advanced/index.md
- async.md
@@ -97,6 +101,8 @@ extra:
name: es - español
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/

View File

@@ -0,0 +1,446 @@
# Alternatives, inspiration et comparaisons
Ce qui a inspiré **FastAPI**, comment il se compare à d'autres solutions et ce qu'il en a appris.
## Intro
**FastAPI** n'existerait pas sans les précédentes contributions d'autres projets.
De nombreux outils ont été créés auparavant et ont contribué à inspirer sa création.
J'ai évité la création d'un nouveau framework pendant plusieurs années. J'ai d'abord essayé de combler toutes les
fonctionnalités couvertes par **FastAPI** en utilisant de nombreux frameworks, plug-ins et outils différents.
Mais à un moment donné il n'y avait pas d'autre option que de créer quelque chose qui offrait toutes ces
fonctionnalités, en reprenant et en combinant de la meilleure façon possible les meilleures idées des outils
précédents, en utilisant des fonctionnalités du langage qui n'étaient même pas disponibles auparavant (type hints depuis Python 3.6+).
## Outils précédents
### <a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a>
C'est le framework Python le plus populaire et il bénéficie d'une grande confiance. Il est utilisé pour construire
des systèmes tel qu'Instagram.
Il est relativement fortement couplé aux bases de données relationnelles (comme MySQL ou PostgreSQL), de sorte qu'il
n'est pas très facile d'utiliser une base de données NoSQL (comme Couchbase, MongoDB, Cassandra, etc.) comme principal moyen de
stockage.
Il a été créé pour générer le HTML en backend, pas pour créer des API consommées par un frontend moderne (comme React, Vue.js et Angular) ou par d'autres systèmes (comme les appareils <abbr title="Internet of Things">IoT</abbr>) communiquant avec lui.
### <a href="https://www.django-rest-framework.org/" class="external-link" target="_blank">Django REST Framework</a>
Django REST framework a été conçu comme une boîte à outils flexible permettant de construire des API Web à partir de Django, afin d'améliorer ses capacités en matière d'API.
Il est utilisé par de nombreuses entreprises, dont Mozilla, Red Hat et Eventbrite.
Il s'agissait de l'un des premiers exemples de **documentation automatique pour API**, et c'est précisément l'une des
premières idées qui a inspiré "la recherche de" **FastAPI**.
!!! note
Django REST framework a été créé par Tom Christie. Le créateur de Starlette et Uvicorn, sur lesquels **FastAPI** est basé.
!!! check "A inspiré **FastAPI** à"
Avoir une interface de documentation automatique de l'API.
### <a href="https://flask.palletsprojects.com" class="external-link" target="_blank">Flask</a>
Flask est un "micro-framework", il ne comprend pas d'intégrations de bases de données ni beaucoup de choses qui sont fournies par défaut dans Django.
Cette simplicité et cette flexibilité permettent d'utiliser des bases de données NoSQL comme principal système de stockage de données.
Comme il est très simple, son apprentissage est relativement intuitif, bien que la documentation soit quelque peu
technique par moments.
Il est aussi couramment utilisé pour d'autres applications qui n'ont pas nécessairement besoin d'une base de données, de gestion des utilisateurs ou de l'une des nombreuses fonctionnalités préinstallées dans Django. Bien que beaucoup de ces fonctionnalités puissent être ajoutées avec des plug-ins.
Ce découplage des parties, et le fait d'être un "micro-framework" qui puisse être étendu pour couvrir exactement ce
qui est nécessaire, était une caractéristique clé que je voulais conserver.
Compte tenu de la simplicité de Flask, il semblait bien adapté à la création d'API. La prochaine chose à trouver était un "Django REST Framework" pour Flask.
!!! check "A inspiré **FastAPI** à"
Être un micro-framework. Il est donc facile de combiner les outils et les pièces nécessaires.
Proposer un système de routage simple et facile à utiliser.
### <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a>
**FastAPI** n'est pas réellement une alternative à **Requests**. Leur cadre est très différent.
Il serait en fait plus courant d'utiliser Requests _à l'intérieur_ d'une application FastAPI.
Mais quand même, FastAPI s'est inspiré de Requests.
**Requests** est une bibliothèque pour _interagir_ avec les API (en tant que client), tandis que **FastAPI** est une bibliothèque pour _créer_ des API (en tant que serveur).
Ils sont, plus ou moins, aux extrémités opposées, se complétant l'un l'autre.
Requests a un design très simple et intuitif, il est très facile à utiliser, avec des valeurs par défaut raisonnables, tout en étant très puissant et personnalisable.
C'est pourquoi, comme le dit le site officiel :
> Requests est l'un des packages Python les plus téléchargés de tous les temps
La façon dont vous l'utilisez est très simple. Par exemple, pour faire une requête `GET`, vous devez écrire :
```Python
response = requests.get("http://example.com/some/url")
```
En contrepartie l'API _des opérations de chemin_ de FastAPI pourrait ressembler à ceci :
```Python hl_lines="1"
@app.get("/some/url")
def read_url():
return {"message": "Hello World"}
```
Notez les similitudes entre `requests.get(...)` et `@app.get(...)`.
!!! check "A inspiré **FastAPI** à"
_ Avoir une API simple et intuitive.
_ Utiliser les noms de méthodes HTTP (opérations) directement, de manière simple et intuitive. \* Avoir des valeurs par défaut raisonnables, mais des personnalisations puissantes.
### <a href="https://swagger.io/" class="external-link" target="_blank">Swagger</a> / <a href="https://github.com/OAI/OpenAPI-Specification/" class="external-link" target="_blank">OpenAPI</a>
La principale fonctionnalité que j'ai emprunté à Django REST Framework était la documentation automatique des API.
Puis j'ai découvert qu'il existait une norme pour documenter les API, en utilisant JSON (ou YAML, une extension de JSON) appelée Swagger.
Il existait déjà une interface utilisateur Web pour les API Swagger. Donc, être capable de générer une documentation
Swagger pour une API permettrait d'utiliser cette interface utilisateur web automatiquement.
À un moment donné, Swagger a été cédé à la Fondation Linux, puis a été rebaptisé OpenAPI.
C'est pourquoi, lorsqu'on parle de la version 2.0, il est courant de dire "Swagger", et pour la version 3+ "OpenAPI".
!!! check "A inspiré **FastAPI** à"
Adopter et utiliser une norme ouverte pour les spécifications des API, au lieu d'un schéma personnalisé.
Intégrer des outils d'interface utilisateur basés sur des normes :
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>
* <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>
Ces deux-là ont été choisis parce qu'ils sont populaires et stables, mais en faisant une recherche rapide, vous pourriez trouver des dizaines d'alternatives supplémentaires pour OpenAPI (que vous pouvez utiliser avec **FastAPI**).
### Frameworks REST pour Flask
Il y a plusieurs frameworks REST pour Flask, mais après avoir investi du temps et du travail pour les étudier, j'ai
découvert que le développement de beaucoup d'entre eux sont suspendus ou abandonnés, avec plusieurs problèmes
permanents qui les rendent inadaptés.
### <a href="https://marshmallow.readthedocs.io/en/3.0/" class="external-link" target="_blank">Marshmallow</a>
L'une des principales fonctionnalités nécessaires aux systèmes API est la "<abbr title="également appelée
marshalling, conversion">sérialisation</abbr>" des données, qui consiste à prendre les données du code (Python) et à
les convertir en quelque chose qui peut être envoyé sur le réseau. Par exemple, convertir un objet contenant des
données provenant d'une base de données en un objet JSON. Convertir des objets `datetime` en strings, etc.
La validation des données est une autre fonctionnalité importante dont ont besoin les API. Elle permet de s'assurer
que les données sont valides, compte tenu de certains paramètres. Par exemple, qu'un champ est un `int`, et non un
string.
Ceci est particulièrement utile pour les données entrantes.
Sans un système de validation des données, vous devriez effectuer toutes les vérifications à la main, dans le code.
Ces fonctionnalités sont ce pourquoi Marshmallow a été construit. C'est une excellente bibliothèque, et je l'ai déjà beaucoup utilisée.
Mais elle a été créée avant que les type hints n'existent en Python. Ainsi, pour définir chaque <abbr title="la définition de
la façon dont les données doivent être formées">schéma</abbr>, vous devez utiliser des utilitaires et des classes spécifiques fournies par Marshmallow.
!!! check "A inspiré **FastAPI** à"
Utilisez du code pour définir des "schémas" qui fournissent automatiquement les types de données et la validation.
### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a>
Une autre grande fonctionnalité requise par les API est le <abbr title="la lecture et la conversion en données
Python">parsing</abbr> des données provenant des requêtes entrantes.
Webargs est un outil qui a été créé pour fournir cela par-dessus plusieurs frameworks, dont Flask.
Il utilise Marshmallow pour effectuer la validation des données. Et il a été créé par les mêmes développeurs.
C'est un outil formidable et je l'ai beaucoup utilisé aussi, avant d'avoir **FastAPI**.
!!! info
Webargs a été créé par les développeurs de Marshmallow.
!!! check "A inspiré **FastAPI** à"
Disposer d'une validation automatique des données des requêtes entrantes.
### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a>
Marshmallow et Webargs fournissent la validation, l'analyse et la sérialisation en tant que plug-ins.
Mais la documentation fait toujours défaut. C'est alors qu'APISpec a été créé.
Il s'agit d'un plug-in pour de nombreux frameworks (et il existe également un plug-in pour Starlette).
Le principe est le suivant : vous écrivez la définition du schéma au format YAML dans la docstring de chaque fonction gérant une route.
Et il génère des schémas OpenAPI.
C'est ainsi que cela fonctionne dans Flask, Starlette, Responder, etc.
Mais alors, nous avons à nouveau le problème d'avoir une micro-syntaxe, dans une docstring Python (un gros morceau de YAML).
L'éditeur ne peut guère aider en la matière. Et si nous modifions les paramètres ou les schémas Marshmallow et que nous oublions de modifier également cette docstring YAML, le schéma généré deviendrait obsolète.
!!! info
APISpec a été créé par les développeurs de Marshmallow.
!!! check "A inspiré **FastAPI** à"
Supporter la norme ouverte pour les API, OpenAPI.
### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a>
C'est un plug-in pour Flask, qui relie Webargs, Marshmallow et APISpec.
Il utilise les informations de Webargs et Marshmallow pour générer automatiquement des schémas OpenAPI, en utilisant APISpec.
C'est un excellent outil, très sous-estimé. Il devrait être beaucoup plus populaire que de nombreux plug-ins Flask. C'est peut-être dû au fait que sa documentation est trop concise et abstraite.
Cela a permis de ne pas avoir à écrire YAML (une autre syntaxe) à l'intérieur des docstrings Python.
Cette combinaison de Flask, Flask-apispec avec Marshmallow et Webargs était ma stack backend préférée jusqu'à la création de **FastAPI**.
Son utilisation a conduit à la création de plusieurs générateurs Flask full-stack. Ce sont les principales stacks que
j'ai (ainsi que plusieurs équipes externes) utilisées jusqu'à présent :
- <a href="https://github.com/tiangolo/full-stack" class="external-link" target="_blank">https://github.com/tiangolo/full-stack</a>
- <a href="https://github.com/tiangolo/full-stack-flask-couchbase" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchbase</a>
- <a href="https://github.com/tiangolo/full-stack-flask-couchdb" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchdb</a>
Ces mêmes générateurs full-stack ont servi de base aux [Générateurs de projets pour **FastAPI**](project-generation.md){.internal-link target=\_blank}.
!!! info
Flask-apispec a été créé par les développeurs de Marshmallow.
!!! check "A inspiré **FastAPI** à"
Générer le schéma OpenAPI automatiquement, à partir du même code qui définit la sérialisation et la validation.
### <a href="https://nestjs.com/" class="external-link" target="_blank">NestJS</a> (et <a href="https://angular.io/" class="external-link" target="_blank">Angular</a>)
Ce n'est même pas du Python, NestJS est un framework JavaScript (TypeScript) NodeJS inspiré d'Angular.
Il réalise quelque chose de similaire à ce qui peut être fait avec Flask-apispec.
Il possède un système d'injection de dépendances intégré, inspiré d'Angular 2. Il nécessite de pré-enregistrer les "injectables" (comme tous les autres systèmes d'injection de dépendances que je connais), donc, cela ajoute à la verbosité et à la répétition du code.
Comme les paramètres sont décrits avec des types TypeScript (similaires aux type hints de Python), la prise en charge
par l'éditeur est assez bonne.
Mais comme les données TypeScript ne sont pas préservées après la compilation en JavaScript, il ne peut pas compter sur les types pour définir la validation, la sérialisation et la documentation en même temps. En raison de cela et de certaines décisions de conception, pour obtenir la validation, la sérialisation et la génération automatique de schémas, il est nécessaire d'ajouter des décorateurs à de nombreux endroits. Cela devient donc assez verbeux.
Il ne peut pas très bien gérer les modèles imbriqués. Ainsi, si le corps JSON de la requête est un objet JSON comportant des champs internes qui sont à leur tour des objets JSON imbriqués, il ne peut pas être correctement documenté et validé.
!!! check "A inspiré **FastAPI** à"
Utiliser les types Python pour bénéficier d'un excellent support de l'éditeur.
Disposer d'un puissant système d'injection de dépendances. Trouver un moyen de minimiser la répétition du code.
### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a>
C'était l'un des premiers frameworks Python extrêmement rapides basés sur `asyncio`. Il a été conçu pour être très similaire à Flask.
!!! note "Détails techniques"
Il utilisait <a href="https://github.com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a> au lieu du système par défaut de Python `asyncio`. C'est ce qui l'a rendu si rapide.
Il a clairement inspiré Uvicorn et Starlette, qui sont actuellement plus rapides que Sanic dans les benchmarks.
!!! check "A inspiré **FastAPI** à"
Trouvez un moyen d'avoir une performance folle.
C'est pourquoi **FastAPI** est basé sur Starlette, car il s'agit du framework le plus rapide disponible (testé par des benchmarks tiers).
### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a>
Falcon est un autre framework Python haute performance, il est conçu pour être minimal, et est utilisé comme fondation pour d'autres frameworks comme Hug.
Il utilise le standard précédent pour les frameworks web Python (WSGI) qui est synchrone, donc il ne peut pas gérer les WebSockets et d'autres cas d'utilisation. Néanmoins, il offre de très bonnes performances.
Il est conçu pour avoir des fonctions qui reçoivent deux paramètres, une "requête" et une "réponse". Ensuite, vous
"lisez" des parties de la requête et "écrivez" des parties dans la réponse. En raison de cette conception, il n'est
pas possible de déclarer des paramètres de requête et des corps avec des indications de type Python standard comme paramètres de fonction.
Ainsi, la validation, la sérialisation et la documentation des données doivent être effectuées dans le code, et non pas automatiquement. Ou bien elles doivent être implémentées comme un framework au-dessus de Falcon, comme Hug. Cette même distinction se retrouve dans d'autres frameworks qui s'inspirent de la conception de Falcon, qui consiste à avoir un objet de requête et un objet de réponse comme paramètres.
!!! check "A inspiré **FastAPI** à"
Trouver des moyens d'obtenir de bonnes performances.
Avec Hug (puisque Hug est basé sur Falcon), **FastAPI** a inspiré la déclaration d'un paramètre `response` dans les fonctions.
Bien que dans FastAPI, il est facultatif, et est utilisé principalement pour définir les en-têtes, les cookies, et les codes de statut alternatifs.
### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a>
J'ai découvert Molten lors des premières étapes de développement de **FastAPI**. Et il a des idées assez similaires :
- Basé sur les type hints Python.
- Validation et documentation via ces types.
- Système d'injection de dépendances.
Il n'utilise pas une librairie tiers de validation, sérialisation et de documentation tel que Pydantic, il utilise son propre système. Ainsi, ces définitions de types de données ne sont pas réutilisables aussi facilement.
Il nécessite une configuration un peu plus verbeuse. Et comme il est basé sur WSGI (au lieu dASGI), il n'est pas
conçu pour profiter des hautes performances fournies par des outils comme Uvicorn, Starlette et Sanic.
Le système d'injection de dépendances exige le pré-enregistrement des dépendances et les dépendances sont résolues sur la base des types déclarés. Ainsi, il n'est pas possible de déclarer plus d'un "composant" qui fournit un certain type.
Les routes sont déclarées à un seul endroit, en utilisant des fonctions déclarées à d'autres endroits (au lieu
d'utiliser des décorateurs qui peuvent être placés juste au-dessus de la fonction qui gère l'endpoint). Cette
méthode est plus proche de celle de Django que de celle de Flask (et Starlette). Il sépare dans le code des choses
qui sont relativement fortement couplées.
!!! check "A inspiré **FastAPI** à"
Définir des validations supplémentaires pour les types de données utilisant la valeur "par défaut" des attributs du modèle. Ceci améliore le support de l'éditeur, et n'était pas disponible dans Pydantic auparavant.
Cela a en fait inspiré la mise à jour de certaines parties de Pydantic, afin de supporter le même style de déclaration de validation (toute cette fonctionnalité est maintenant déjà disponible dans Pydantic).
### <a href="https://www.hug.rest/" class="external-link" target="_blank">Hug</a>
Hug a été l'un des premiers frameworks à implémenter la déclaration des types de paramètres d'API en utilisant les type hints Python. C'était une excellente idée qui a inspiré d'autres outils à faire de même.
Il utilisait des types personnalisés dans ses déclarations au lieu des types Python standard, mais c'était tout de même un énorme pas en avant.
Il a également été l'un des premiers frameworks à générer un schéma personnalisé déclarant l'ensemble de l'API en JSON.
Il n'était pas basé sur une norme comme OpenAPI et JSON Schema. Il ne serait donc pas simple de l'intégrer à d'autres outils, comme Swagger UI. Mais encore une fois, c'était une idée très innovante.
Il présente une caractéristique intéressante et peu commune : à l'aide du même framework, il est possible de créer des
API et des CLI.
Comme il est basé sur l'ancienne norme pour les frameworks web Python synchrones (WSGI), il ne peut pas gérer les Websockets et autres, bien qu'il soit également très performant.
!!! info
Hug a été créé par Timothy Crosley, le créateur de <a href="https://github.com/timothycrosley/isort" class="external-link" target="_blank">`isort`</a>, un excellent outil pour trier automatiquement les imports dans les fichiers Python.
!!! check "A inspiré **FastAPI** à"
Hug a inspiré certaines parties d'APIStar, et était l'un des outils que je trouvais les plus prometteurs, à côté d'APIStar.
Hug a contribué à inspirer **FastAPI** pour utiliser les type hints Python
pour déclarer les paramètres, et pour générer automatiquement un schéma définissant l'API.
Hug a inspiré **FastAPI** pour déclarer un paramètre `response` dans les fonctions pour définir les en-têtes et les cookies.
### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (<= 0.5)
Juste avant de décider de développer **FastAPI**, j'ai trouvé le serveur **APIStar**. Il contenait presque tout ce
que je recherchais et avait un beau design.
C'était l'une des premières implémentations d'un framework utilisant les type hints Python pour déclarer les paramètres
et les requêtes que j'ai vues (avant NestJS et Molten). Je l'ai trouvé plus ou moins en même temps que Hug. Mais APIStar utilisait le standard OpenAPI.
Il disposait de la validation automatique, sérialisation des données et d'une génération de schéma OpenAPI basée sur les mêmes type hints à plusieurs endroits.
La définition du schéma de corps de requête n'utilisait pas les mêmes type hints Python que Pydantic, il était un peu plus proche de Marshmallow, donc le support de l'éditeur n'était pas aussi bon, mais APIStar était quand même la meilleure option disponible.
Il avait les meilleures performances d'après les benchmarks de l'époque (seulement surpassé par Starlette).
Au départ, il ne disposait pas d'une interface web de documentation automatique de l'API, mais je savais que je pouvais lui ajouter une interface Swagger.
Il avait un système d'injection de dépendances. Il nécessitait un pré-enregistrement des composants, comme d'autres outils discutés ci-dessus. Mais c'était quand même une excellente fonctionnalité.
Je n'ai jamais pu l'utiliser dans un projet complet, car il n'avait pas d'intégration de sécurité, et je ne pouvais donc pas remplacer toutes les fonctionnalités que j'avais avec les générateurs complets basés sur Flask-apispec. J'avais dans mon backlog de projets de créer une pull request pour ajouter cette fonctionnalité.
Mais ensuite, le projet a changé d'orientation.
Il ne s'agissait plus d'un framework web API, le créateur devant se concentrer sur Starlette.
Maintenant, APIStar est un ensemble d'outils pour valider les spécifications OpenAPI, et non un framework web.
!!! info
APIStar a été créé par Tom Christie. Le même gars qui a créé :
* Django REST Framework
* Starlette (sur lequel **FastAPI** est basé)
* Uvicorn (utilisé par Starlette et **FastAPI**)
!!! check "A inspiré **FastAPI** à"
Exister.
L'idée de déclarer plusieurs choses (validation des données, sérialisation et documentation) avec les mêmes types Python, tout en offrant un excellent support pour les éditeurs, était pour moi une idée brillante.
Et après avoir longtemps cherché un framework similaire et testé de nombreuses alternatives, APIStar était la meilleure option disponible.
Puis APIStar a cessé d'exister en tant que serveur et Starlette a été créé, et a constitué une meilleure base pour un tel système. Ce fut l'inspiration finale pour construire **FastAPI**.
Je considère **FastAPI** comme un "successeur spirituel" d'APIStar, tout en améliorant et en augmentant les fonctionnalités, le système de typage et d'autres parties, sur la base des enseignements tirés de tous ces outils précédents.
## Utilisés par **FastAPI**
### <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a>
Pydantic est une bibliothèque permettant de définir la validation, la sérialisation et la documentation des données (à l'aide de JSON Schema) en se basant sur les Python type hints.
Cela le rend extrêmement intuitif.
Il est comparable à Marshmallow. Bien qu'il soit plus rapide que Marshmallow dans les benchmarks. Et comme il est
basé sur les mêmes type hints Python, le support de l'éditeur est grand.
!!! check "**FastAPI** l'utilise pour"
Gérer toute la validation des données, leur sérialisation et la documentation automatique du modèle (basée sur le schéma JSON).
**FastAPI** prend ensuite ces données JSON Schema et les place dans OpenAPI, en plus de toutes les autres choses qu'il fait.
### <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>
Starlette est un framework/toolkit léger <abbr title="Le nouveau standard pour construire des applications web assynchrones en Python">ASGI</abbr>, qui est idéal pour construire des services asyncio performants.
Il est très simple et intuitif. Il est conçu pour être facilement extensible et avoir des composants modulaires.
Il offre :
- Des performances vraiment impressionnantes.
- Le support des WebSockets.
- Le support de GraphQL.
- Les tâches d'arrière-plan.
- Les événements de démarrage et d'arrêt.
- Un client de test basé sur request.
- CORS, GZip, fichiers statiques, streaming des réponses.
- Le support des sessions et des cookies.
- Une couverture de test à 100 %.
- 100 % de la base de code avec des annotations de type.
- Zéro forte dépendance à d'autres packages.
Starlette est actuellement le framework Python le plus rapide testé. Seulement dépassé par Uvicorn, qui n'est pas un framework, mais un serveur.
Starlette fournit toutes les fonctionnalités de base d'un micro-framework web.
Mais il ne fournit pas de validation automatique des données, de sérialisation ou de documentation.
C'est l'une des principales choses que **FastAPI** ajoute par-dessus, le tout basé sur les type hints Python (en utilisant Pydantic). Cela, plus le système d'injection de dépendances, les utilitaires de sécurité, la génération de schémas OpenAPI, etc.
!!! note "Détails techniques"
ASGI est une nouvelle "norme" développée par les membres de l'équipe principale de Django. Il ne s'agit pas encore d'une "norme Python" (un PEP), bien qu'ils soient en train de le faire.
Néanmoins, il est déjà utilisé comme "standard" par plusieurs outils. Cela améliore grandement l'interopérabilité, puisque vous pouvez remplacer Uvicorn par n'importe quel autre serveur ASGI (comme Daphne ou Hypercorn), ou vous pouvez ajouter des outils compatibles ASGI, comme `python-socketio`.
!!! check "**FastAPI** l'utilise pour"
Gérer toutes les parties web de base. Ajouter des fonctionnalités par-dessus.
La classe `FastAPI` elle-même hérite directement de la classe `Starlette`.
Ainsi, tout ce que vous pouvez faire avec Starlette, vous pouvez le faire directement avec **FastAPI**, car il s'agit en fait de Starlette sous stéroïdes.
### <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>
Uvicorn est un serveur ASGI rapide comme l'éclair, basé sur uvloop et httptools.
Il ne s'agit pas d'un framework web, mais d'un serveur. Par exemple, il ne fournit pas d'outils pour le routing. C'est
quelque chose qu'un framework comme Starlette (ou **FastAPI**) fournirait par-dessus.
C'est le serveur recommandé pour Starlette et **FastAPI**.
!!! check "**FastAPI** le recommande comme"
Le serveur web principal pour exécuter les applications **FastAPI**.
Vous pouvez le combiner avec Gunicorn, pour avoir un serveur multi-processus asynchrone.
Pour plus de détails, consultez la section [Déploiement](deployment/index.md){.internal-link target=_blank}.
## Benchmarks et vitesse
Pour comprendre, comparer et voir la différence entre Uvicorn, Starlette et FastAPI, consultez la section sur les [Benchmarks](benchmarks.md){.internal-link target=\_blank}.

View File

@@ -0,0 +1,82 @@
# Articles et liens externes
**FastAPI** possède une grande communauté en constante extension.
Il existe de nombreux articles, outils et projets liés à **FastAPI**.
Voici une liste incomplète de certains d'entre eux.
!!! tip "Astuce"
Si vous avez un article, projet, outil, ou quoi que ce soit lié à **FastAPI** qui n'est actuellement pas listé ici, créez une <a href="https://github.com/tiangolo/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">Pull Request l'ajoutant</a>.
## Articles
### Anglais
{% if external_links %}
{% for article in external_links.articles.english %}
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> par <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
{% endfor %}
{% endif %}
### Japonais
{% if external_links %}
{% for article in external_links.articles.japanese %}
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> par <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
{% endfor %}
{% endif %}
### Vietnamien
{% if external_links %}
{% for article in external_links.articles.vietnamese %}
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> par <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
{% endfor %}
{% endif %}
### Russe
{% if external_links %}
{% for article in external_links.articles.russian %}
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> par <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
{% endfor %}
{% endif %}
### Allemand
{% if external_links %}
{% for article in external_links.articles.german %}
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> par <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
{% endfor %}
{% endif %}
## Podcasts
{% if external_links %}
{% for article in external_links.podcasts.english %}
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> par <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
{% endfor %}
{% endif %}
## Conférences
{% if external_links %}
{% for article in external_links.talks.english %}
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> par <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
{% endfor %}
{% endif %}
## Projets
Les projets Github avec le topic `fastapi` les plus récents :
<div class="github-topic-projects">
</div>

View File

@@ -0,0 +1,84 @@
# Génération de projets - Modèle
Vous pouvez utiliser un générateur de projet pour commencer, qui réalisera pour vous la mise en place de bases côté architecture globale, sécurité, base de données et premières routes d'API.
Un générateur de projet fera toujours une mise en place très subjective que vous devriez modifier et adapter suivant vos besoins, mais cela reste un bon point de départ pour vos projets.
## Full Stack FastAPI PostgreSQL
GitHub : <a href="https://github.com/tiangolo/full-stack-fastapi-postgresql" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-fastapi-postgresql</a>
### Full Stack FastAPI PostgreSQL - Fonctionnalités
* Intégration **Docker** complète (basée sur Docker).
* Déploiement Docker en mode <a href="https://docs.docker.com/engine/swarm/" class="external-link" target="_blank">Swarm</a>
* Intégration **Docker Compose** et optimisation pour développement local.
* Serveur web Python **prêt au déploiement** utilisant Uvicorn et Gunicorn.
* Backend Python <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">**FastAPI**</a> :
* **Rapide** : Très hautes performances, comparables à **NodeJS** ou **Go** (grâce à Starlette et Pydantic).
* **Intuitif** : Excellent support des éditeurs. <abbr title="aussi appelée auto-complétion, autocomplétion, IntelliSense...">Complétion</abbr> partout. Moins de temps passé à déboguer.
* **Facile** : Fait pour être facile à utiliser et apprendre. Moins de temps passé à lire de la documentation.
* **Concis** : Minimise la duplication de code. Plusieurs fonctionnalités à chaque déclaration de paramètre.
* **Robuste** : Obtenez du code prêt pour être utilisé en production. Avec de la documentation automatique interactive.
* **Basé sur des normes** : Basé sur (et totalement compatible avec) les normes ouvertes pour les APIs : <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> et <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
* <a href="https://fastapi.tiangolo.com/features/" class="external-link" target="_blank">**Et bien d'autres fonctionnalités**</a> comme la validation automatique, la sérialisation, l'authentification avec OAuth2 JWT tokens, etc.
* Hashage de **mots de passe sécurisé** par défaut.
* Authentification par **jetons JWT**.
* Modèles **SQLAlchemy** (indépendants des extensions Flask, afin qu'ils puissent être utilisés directement avec des *workers* Celery).
* Modèle de démarrages basiques pour les utilisateurs (à modifier et supprimer au besoin).
* Migrations **Alembic**.
* **CORS** (partage des ressources entre origines multiples, ou *Cross Origin Resource Sharing*).
* *Worker* **Celery** pouvant importer et utiliser les modèles et le code du reste du backend.
* Tests du backend REST basés sur **Pytest**, intégrés dans Docker, pour que vous puissiez tester toutes les interactions de l'API indépendamment de la base de données. Étant exécutés dans Docker, les tests peuvent utiliser un nouvel entrepôt de données créé de zéro à chaque fois (vous pouvez donc utiliser ElasticSearch, MongoDB, CouchDB, etc. et juste tester que l'API fonctionne).
* Intégration Python facile avec **Jupyter Kernels** pour le développement à distance ou intra-Docker avec des extensions comme Atom Hydrogen ou Visual Studio Code Jupyter.
* Frontend **Vue** :
* Généré avec Vue CLI.
* Gestion de l'**Authentification JWT**.
* Page de connexion.
* Après la connexion, page de tableau de bord principal.
* Tableau de bord principal avec création et modification d'utilisateurs.
* Modification de ses propres caractéristiques utilisateur.
* **Vuex**.
* **Vue-router**.
* **Vuetify** pour de magnifiques composants *material design*.
* **TypeScript**.
* Serveur Docker basé sur **Nginx** (configuré pour être facilement manipulé avec Vue-router).
* Utilisation de *Docker multi-stage building*, pour ne pas avoir besoin de sauvegarder ou *commit* du code compilé.
* Tests frontend exécutés à la compilation (pouvant être désactivés).
* Fait aussi modulable que possible, pour pouvoir fonctionner comme tel, tout en pouvant être utilisé qu'en partie grâce à Vue CLI.
* **PGAdmin** pour les bases de données PostgreSQL, facilement modifiable pour utiliser PHPMYAdmin ou MySQL.
* **Flower** pour la surveillance de tâches Celery.
* Équilibrage de charge entre le frontend et le backend avec **Traefik**, afin de pouvoir avoir les deux sur le même domaine, séparés par chemins, mais servis par différents conteneurs.
* Intégration Traefik, comprenant la génération automatique de certificat **HTTPS** Let's Encrypt.
* GitLab **CI** (intégration continue), comprenant des tests pour le frontend et le backend.
## Full Stack FastAPI Couchbase
GitHub : <a href="https://github.com/tiangolo/full-stack-fastapi-couchbase" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-fastapi-couchbase</a>
⚠️ **ATTENTION** ⚠️
Si vous démarrez un nouveau projet de zéro, allez voir les alternatives au début de cette page.
Par exemple, le générateur de projet <a href="https://github.com/tiangolo/full-stack-fastapi-postgresql" class="external-link" target="_blank">Full Stack FastAPI PostgreSQL</a> peut être une meilleure alternative, étant activement maintenu et utilisé et comprenant toutes les nouvelles fonctionnalités et améliorations.
Vous êtes toujours libre d'utiliser le générateur basé sur Couchbase si vous le voulez, cela devrait probablement fonctionner correctement, et si vous avez déjà un projet généré en utilisant ce dernier, cela devrait fonctionner aussi (et vous l'avez déjà probablement mis à jour suivant vos besoins).
Vous pouvez en apprendre plus dans la documentation du dépôt GithHub.
## Full Stack FastAPI MongoDB
...viendra surement plus tard, suivant le temps que j'ai. 😅 🎉
## Modèles d'apprentissage automatique avec spaCy et FastAPI
GitHub : <a href="https://github.com/microsoft/cookiecutter-spacy-fastapi" class="external-link" target="_blank">https://github.com/microsoft/cookiecutter-spacy-fastapi</a>
## Modèles d'apprentissage automatique avec spaCy et FastAPI - Fonctionnalités
* Intégration d'un modèle NER **spaCy**.
* Formatage de requête pour **Azure Cognitive Search**.
* Serveur Python web **prêt à utiliser en production** utilisant Uvicorn et Gunicorn.
* Déploiement CI/CD Kubernetes pour **Azure DevOps** (AKS).
* **Multilangues**. Choisissez facilement l'une des langues intégrées à spaCy durant la mise en place du projet.
* **Facilement généralisable** à d'autres bibliothèques similaires (Pytorch, Tensorflow), et non juste spaCy.

View File

@@ -0,0 +1,314 @@
# Introduction aux Types Python
Python supporte des annotations de type (ou *type hints*) optionnelles.
Ces annotations de type constituent une syntaxe spéciale qui permet de déclarer le <abbr title="par exemple : str, int, float, bool">type</abbr> d'une variable.
En déclarant les types de vos variables, cela permet aux différents outils comme les éditeurs de texte d'offrir un meilleur support.
Ce chapitre n'est qu'un **tutoriel rapide / rappel** sur les annotations de type Python.
Seulement le minimum nécessaire pour les utiliser avec **FastAPI** sera couvert... ce qui est en réalité très peu.
**FastAPI** est totalement basé sur ces annotations de type, qui lui donnent de nombreux avantages.
Mais même si vous n'utilisez pas ou n'utiliserez jamais **FastAPI**, vous pourriez bénéficier d'apprendre quelques choses sur ces dernières.
!!! note
Si vous êtes un expert Python, et que vous savez déjà **tout** sur les annotations de type, passez au chapitre suivant.
## Motivations
Prenons un exemple simple :
```Python
{!../../../docs_src/python_types/tutorial001.py!}
```
Exécuter ce programe affiche :
```
John Doe
```
La fonction :
* Prend un `first_name` et un `last_name`.
* Convertit la première lettre de chaque paramètre en majuscules grâce à `title()`.
* Concatène les résultats avec un espace entre les deux.
```Python hl_lines="2"
{!../../../docs_src/python_types/tutorial001.py!}
```
### Limitations
C'est un programme très simple.
Mais maintenant imaginez que vous l'écriviez de zéro.
À un certain point vous auriez commencé la définition de la fonction, vous aviez les paramètres prêts.
Mais vous aviez besoin de "cette méthode qui convertit la première lettre en majuscule".
Était-ce `upper` ? `uppercase` ? `first_uppercase` ? `capitalize` ?
Vous essayez donc d'utiliser le vieil ami du programmeur, l'auto-complétion de l'éditeur.
Vous écrivez le premier paramètre, `first_name`, puis un point (`.`) et appuyez sur `Ctrl+Espace` pour déclencher l'auto-complétion.
Mais malheureusement, rien d'utile n'en résulte :
<img src="/img/python-types/image01.png">
### Ajouter des types
Modifions une seule ligne de la version précédente.
Nous allons changer seulement cet extrait, les paramètres de la fonction, de :
```Python
first_name, last_name
```
à :
```Python
first_name: str, last_name: str
```
C'est tout.
Ce sont des annotations de types :
```Python hl_lines="1"
{!../../../docs_src/python_types/tutorial002.py!}
```
À ne pas confondre avec la déclaration de valeurs par défaut comme ici :
```Python
first_name="john", last_name="doe"
```
C'est une chose différente.
On utilise un deux-points (`:`), et pas un égal (`=`).
Et ajouter des annotations de types ne crée normalement pas de différence avec le comportement qui aurait eu lieu si elles n'étaient pas là.
Maintenant, imaginez que vous êtes en train de créer cette fonction, mais avec des annotations de type cette fois.
Au même moment que durant l'exemple précédent, vous essayez de déclencher l'auto-complétion et vous voyez :
<img src="/img/python-types/image02.png">
Vous pouvez donc dérouler les options jusqu'à trouver la méthode à laquelle vous pensiez.
<img src="/img/python-types/image03.png">
## Plus de motivations
Cette fonction possède déjà des annotations de type :
```Python hl_lines="1"
{!../../../docs_src/python_types/tutorial003.py!}
```
Comme l'éditeur connaît le type des variables, vous n'avez pas seulement l'auto-complétion, mais aussi de la détection d'erreurs :
<img src="/img/python-types/image04.png">
Maintenant que vous avez connaissance du problème, convertissez `age` en <abbr title="string">chaine de caractères</abbr> grâce à `str(age)` :
```Python hl_lines="2"
{!../../../docs_src/python_types/tutorial004.py!}
```
## Déclarer des types
Vous venez de voir là où les types sont généralement déclarés : dans les paramètres de fonctions.
C'est aussi ici que vous les utiliseriez avec **FastAPI**.
### Types simples
Vous pouvez déclarer tous les types de Python, pas seulement `str`.
Comme par exemple :
* `int`
* `float`
* `bool`
* `bytes`
```Python hl_lines="1"
{!../../../docs_src/python_types/tutorial005.py!}
```
### Types génériques avec des paramètres de types
Il existe certaines structures de données qui contiennent d'autres valeurs, comme `dict`, `list`, `set` et `tuple`. Et les valeurs internes peuvent elles aussi avoir leurs propres types.
Pour déclarer ces types et les types internes, on utilise le module standard de Python `typing`.
Il existe spécialement pour supporter ces annotations de types.
#### `List`
Par exemple, définissons une variable comme `list` de `str`.
Importez `List` (avec un `L` majuscule) depuis `typing`.
```Python hl_lines="1"
{!../../../docs_src/python_types/tutorial006.py!}
```
Déclarez la variable, en utilisant la syntaxe des deux-points (`:`).
Et comme type, mettez `List`.
Les listes étant un type contenant des types internes, mettez ces derniers entre crochets (`[`, `]`) :
```Python hl_lines="4"
{!../../../docs_src/python_types/tutorial006.py!}
```
!!! tip "Astuce"
Ces types internes entre crochets sont appelés des "paramètres de type".
Ici, `str` est un paramètre de type passé à `List`.
Ce qui signifie : "la variable `items` est une `list`, et chacun de ses éléments a pour type `str`.
En faisant cela, votre éditeur pourra vous aider, même pendant que vous traitez des éléments de la liste.
<img src="/img/python-types/image05.png">
Sans types, c'est presque impossible à réaliser.
Vous remarquerez que la variable `item` n'est qu'un des éléments de la list `items`.
Et pourtant, l'éditeur sait qu'elle est de type `str` et pourra donc vous aider à l'utiliser.
#### `Tuple` et `Set`
C'est le même fonctionnement pour déclarer un `tuple` ou un `set` :
```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial007.py!}
```
Dans cet exemple :
* La variable `items_t` est un `tuple` avec 3 éléments, un `int`, un deuxième `int`, et un `str`.
* La variable `items_s` est un `set`, et chacun de ses éléments est de type `bytes`.
#### `Dict`
Pour définir un `dict`, il faut lui passer 2 paramètres, séparés par une virgule (`,`).
Le premier paramètre de type est pour les clés et le second pour les valeurs du dictionnaire (`dict`).
```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial008.py!}
```
Dans cet exemple :
* La variable `prices` est de type `dict` :
* Les clés de ce dictionnaire sont de type `str`.
* Les valeurs de ce dictionnaire sont de type `float`.
#### `Optional`
Vous pouvez aussi utiliser `Optional` pour déclarer qu'une variable a un type, comme `str` mais qu'il est "optionnel" signifiant qu'il pourrait aussi être `None`.
```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial009.py!}
```
Utiliser `Optional[str]` plutôt que `str` permettra à l'éditeur de vous aider à détecter les erreurs où vous supposeriez qu'une valeur est toujours de type `str`, alors qu'elle pourrait aussi être `None`.
#### Types génériques
Les types qui peuvent contenir des paramètres de types entre crochets, comme :
* `List`
* `Tuple`
* `Set`
* `Dict`
* `Optional`
* ...et d'autres.
sont appelés des **types génériques** ou **Generics**.
### Classes en tant que types
Vous pouvez aussi déclarer une classe comme type d'une variable.
Disons que vous avez une classe `Person`, avec une variable `name` :
```Python hl_lines="1-3"
{!../../../docs_src/python_types/tutorial010.py!}
```
Vous pouvez ensuite déclarer une variable de type `Person` :
```Python hl_lines="6"
{!../../../docs_src/python_types/tutorial010.py!}
```
Et vous aurez accès, encore une fois, au support complet offert par l'éditeur :
<img src="/img/python-types/image06.png">
## Les modèles Pydantic
<a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> est une bibliothèque Python pour effectuer de la validation de données.
Vous déclarez la forme de la donnée avec des classes et des attributs.
Chaque attribut possède un type.
Puis vous créez une instance de cette classe avec certaines valeurs et **Pydantic** validera les valeurs, les convertira dans le type adéquat (si c'est nécessaire et possible) et vous donnera un objet avec toute la donnée.
Ainsi, votre éditeur vous offrira un support adapté pour l'objet résultant.
Extrait de la documentation officielle de **Pydantic** :
```Python
{!../../../docs_src/python_types/tutorial011.py!}
```
!!! info
Pour en savoir plus à propos de <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic, allez jeter un coup d'oeil à sa documentation</a>.
**FastAPI** est basé entièrement sur **Pydantic**.
Vous verrez bien plus d'exemples de son utilisation dans [Tutoriel - Guide utilisateur](tutorial/index.md){.internal-link target=_blank}.
## Les annotations de type dans **FastAPI**
**FastAPI** utilise ces annotations pour faire différentes choses.
Avec **FastAPI**, vous déclarez des paramètres grâce aux annotations de types et vous obtenez :
* **du support de l'éditeur**
* **de la vérification de types**
...et **FastAPI** utilise ces mêmes déclarations pour :
* **Définir les prérequis** : depuis les paramètres de chemins des requêtes, les entêtes, les corps, les dépendances, etc.
* **Convertir des données** : depuis la requête vers les types requis.
* **Valider des données** : venant de chaque requête :
* Générant automatiquement des **erreurs** renvoyées au client quand la donnée est invalide.
* **Documenter** l'API avec OpenAPI :
* ce qui ensuite utilisé par les interfaces utilisateur automatiques de documentation interactive.
Tout cela peut paraître bien abstrait, mais ne vous inquiétez pas, vous verrez tout ça en pratique dans [Tutoriel - Guide utilisateur](tutorial/index.md){.internal-link target=_blank}.
Ce qu'il faut retenir c'est qu'en utilisant les types standard de Python, à un seul endroit (plutôt que d'ajouter plus de classes, de décorateurs, etc.), **FastAPI** fera une grande partie du travail pour vous.
!!! info
Si vous avez déjà lu le tutoriel et êtes revenus ici pour voir plus sur les types, une bonne ressource est la <a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">"cheat sheet" de `mypy`</a>.

View File

@@ -41,6 +41,7 @@ nav:
- en: /
- es: /es/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
@@ -53,8 +54,12 @@ nav:
- zh: /zh/
- features.md
- fastapi-people.md
- python-types.md
- Tutoriel - Guide utilisateur:
- tutorial/background-tasks.md
- project-generation.md
- alternatives.md
- external-links.md
markdown_extensions:
- toc:
permalink: true
@@ -94,6 +99,8 @@ extra:
name: es - español
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/

464
docs/id/docs/index.md Normal file
View File

@@ -0,0 +1,464 @@
{!../../../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>
## Gold Sponsors
<!-- sponsors -->
{% if sponsors %}
{% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
{% endfor %}
{% endif %}
<!-- /sponsors -->
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a>
## Opinions
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
"_Im over the moon excited about **FastAPI**. Its so fun!_"
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, the FastAPI of CLIs
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be used in the terminal instead of a web API, check out <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀
## Requirements
Python 3.6+
FastAPI stands on the shoulders of giants:
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> for the web parts.
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> for the data parts.
## Installation
<div class="termy">
```console
$ pip install fastapi
---> 100%
```
</div>
You will also need an ASGI server, for production such as <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
<div class="termy">
```console
$ pip install uvicorn[standard]
---> 100%
```
</div>
## Example
### Create it
* Create a file `main.py` with:
```Python
from typing import Optional
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
<details markdown="1">
<summary>Or use <code>async def</code>...</summary>
If your code uses `async` / `await`, use `async def`:
```Python hl_lines="9 14"
from typing import Optional
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
**Note**:
If you don't know, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
</details>
### Run it
Run the server with:
<div class="termy">
```console
$ uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [28720]
INFO: Started server process [28722]
INFO: Waiting for application startup.
INFO: Application startup complete.
```
</div>
<details markdown="1">
<summary>About the command <code>uvicorn main:app --reload</code>...</summary>
The command `uvicorn main:app` refers to:
* `main`: the file `main.py` (the Python "module").
* `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
* `--reload`: make the server restart after code changes. Only do this for development.
</details>
### Check it
Open your browser at <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
You will see the JSON response as:
```JSON
{"item_id": 5, "q": "somequery"}
```
You already created an API that:
* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`.
* Both _paths_ take `GET` <em>operations</em> (also known as HTTP _methods_).
* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`.
* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`.
### Interactive API docs
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
You will see the automatic interactive API documentation (provided by <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Alternative API docs
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
You will see the alternative automatic documentation (provided by <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## Example upgrade
Now modify the file `main.py` to receive a body from a `PUT` request.
Declare the body using standard Python types, thanks to Pydantic.
```Python hl_lines="4 9-12 25-27"
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
```
The server should reload automatically (because you added `--reload` to the `uvicorn` command above).
### Interactive API docs upgrade
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
* The interactive API documentation will be automatically updated, including the new body:
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### Alternative API docs upgrade
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
* The alternative documentation will also reflect the new query parameter and body:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Recap
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
You do that with standard modern Python types.
You don't have to learn a new syntax, the methods or classes of a specific library, etc.
Just standard **Python 3.6+**.
For example, for an `int`:
```Python
item_id: int
```
or for a more complex `Item` model:
```Python
item: Item
```
...and with that single declaration you get:
* Editor support, including:
* Completion.
* Type checks.
* Validation of data:
* Automatic and clear errors when the data is invalid.
* Validation even for deeply nested JSON objects.
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network to Python data and types. Reading from:
* JSON.
* Path parameters.
* Query parameters.
* Cookies.
* Headers.
* Forms.
* Files.
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of output data: converting from Python data and types to network data (as JSON):
* Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc).
* `datetime` objects.
* `UUID` objects.
* Database models.
* ...and many more.
* Automatic interactive API documentation, including 2 alternative user interfaces:
* Swagger UI.
* ReDoc.
---
Coming back to the previous code example, **FastAPI** will:
* Validate that there is an `item_id` in the path for `GET` and `PUT` requests.
* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests.
* If it is not, the client will see a useful, clear error.
* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests.
* As the `q` parameter is declared with `= None`, it is optional.
* Without the `None` it would be required (as is the body in the case with `PUT`).
* For `PUT` requests to `/items/{item_id}`, Read the body as JSON:
* Check that it has a required attribute `name` that should be a `str`.
* Check that it has a required attribute `price` that has to be a `float`.
* Check that it has an optional attribute `is_offer`, that should be a `bool`, if present.
* All this would also work for deeply nested JSON objects.
* Convert from and to JSON automatically.
* Document everything with OpenAPI, that can be used by:
* Interactive documentation systems.
* Automatic client code generation systems, for many languages.
* Provide 2 interactive documentation web interfaces directly.
---
We just scratched the surface, but you already get the idea of how it all works.
Try changing the line with:
```Python
return {"item_name": item.name, "item_id": item_id}
```
...from:
```Python
... "item_name": item.name ...
```
...to:
```Python
... "item_price": item.price ...
```
...and see how your editor will auto-complete the attributes and know their types:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
**Spoiler alert**: the tutorial - user guide includes:
* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**.
* How to set **validation constraints** as `maximum_length` or `regex`.
* A very powerful and easy to use **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth.
* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic).
* 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://requests.readthedocs.io" target="_blank"><code>requests</code></a> - Required if you want to use the `TestClient`.
* <a href="https://github.com/Tinche/aiofiles" target="_blank"><code>aiofiles</code></a> - Required if you want to use `FileResponse` or `StaticFiles`.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Required if you want to use the default template configuration.
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Required if you want to support form <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>, with `request.form()`.
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Required for `SessionMiddleware` support.
* <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.

119
docs/id/mkdocs.yml Normal file
View File

@@ -0,0 +1,119 @@
site_name: FastAPI
site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
site_url: https://fastapi.tiangolo.com/id/
theme:
name: material
custom_dir: overrides
palette:
- scheme: default
primary: teal
accent: amber
toggle:
icon: material/lightbulb-outline
name: Switch to light mode
- scheme: slate
primary: teal
accent: amber
toggle:
icon: material/lightbulb
name: Switch to dark mode
features:
- search.suggest
- search.highlight
icon:
repo: fontawesome/brands/github-alt
logo: https://fastapi.tiangolo.com/img/icon-white.svg
favicon: https://fastapi.tiangolo.com/img/favicon.png
language: id
repo_name: tiangolo/fastapi
repo_url: https://github.com/tiangolo/fastapi
edit_uri: ''
google_analytics:
- UA-133183413-1
- auto
plugins:
- search
- markdownextradata:
data: data
nav:
- FastAPI: index.md
- Languages:
- en: /
- es: /es/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
- pt: /pt/
- ru: /ru/
- sq: /sq/
- tr: /tr/
- uk: /uk/
- zh: /zh/
markdown_extensions:
- toc:
permalink: true
- markdown.extensions.codehilite:
guess_lang: false
- markdown_include.include:
base_path: docs
- admonition
- codehilite
- extra
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_div_format ''
- pymdownx.tabbed
extra:
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
- icon: fontawesome/brands/discord
link: https://discord.gg/VQjSZaeJmf
- icon: fontawesome/brands/twitter
link: https://twitter.com/tiangolo
- icon: fontawesome/brands/linkedin
link: https://www.linkedin.com/in/tiangolo
- icon: fontawesome/brands/dev
link: https://dev.to/tiangolo
- icon: fontawesome/brands/medium
link: https://medium.com/@tiangolo
- icon: fontawesome/solid/globe
link: https://tiangolo.com
alternate:
- link: /
name: en - English
- link: /es/
name: es - español
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /pt/
name: pt - português
- link: /ru/
name: ru - русский язык
- link: /sq/
name: sq - shqip
- link: /tr/
name: tr - Türkçe
- link: /uk/
name: uk - українська мова
- link: /zh/
name: zh - 汉语
extra_css:
- https://fastapi.tiangolo.com/css/termynal.css
- https://fastapi.tiangolo.com/css/custom.css
extra_javascript:
- https://unpkg.com/mermaid@8.4.6/dist/mermaid.min.js
- https://fastapi.tiangolo.com/js/termynal.js
- https://fastapi.tiangolo.com/js/custom.js

View File

@@ -0,0 +1,13 @@
{% extends "base.html" %}
{% block announce %}
<a class="announce" href="https://fastapi.tiangolo.com/newsletter/">
<span class="twemoji">
{% include ".icons/material/email.svg" %}
</span> Subscribe to the <strong>FastAPI and friends</strong> newsletter 🎉
</a>
<!-- <a class="announce" href="https://tripetto.app/run/RXZ6OLDBXX?s=dc" target="_blank">
<span class="twemoji">
</span>Fill the first-ever <strong>FastAPI user survey</strong> for a chance to win official <strong>FastAPI and Typer stickers</strong> 🎁
</a> -->
{% endblock %}

View File

@@ -41,6 +41,7 @@ nav:
- en: /
- es: /es/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
@@ -90,6 +91,8 @@ extra:
name: es - español
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/

View File

@@ -41,6 +41,7 @@ nav:
- en: /
- es: /es/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
@@ -129,6 +130,8 @@ extra:
name: es - español
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/

View File

@@ -41,6 +41,7 @@ nav:
- en: /
- es: /es/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
@@ -96,6 +97,8 @@ extra:
name: es - español
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/

View File

@@ -0,0 +1,511 @@
# Desenvolvimento - Contribuindo
Primeiramente, você deveria ver os meios básicos para [ajudar FastAPI e pedir ajuda](help-fastapi.md){.internal-link target=_blank}.
## Desenvolvendo
Se você já clonou o repositório e precisa mergulhar no código, aqui estão algumas orientações para configurar seu ambiente.
### Ambiente virtual com `venv`
Você pode criar um ambiente virtual em um diretório utilizando o módulo `venv` do Python:
<div class="termy">
```console
$ python -m venv env
```
</div>
Isso criará o diretório `./env/` com os binários Python e então você será capaz de instalar pacotes nesse ambiente isolado.
### Ativar o ambiente
Ative o novo ambiente com:
=== "Linux, macOS"
<div class="termy">
```console
$ source ./env/bin/activate
```
</div>
=== "Windows PowerShell"
<div class="termy">
```console
$ .\env\Scripts\Activate.ps1
```
</div>
=== "Windows Bash"
Ou se você usa Bash para Windows (por exemplo <a href="https://gitforwindows.org/" class="external-link" target="_blank">Git Bash</a>):
<div class="termy">
```console
$ source ./env/Scripts/activate
```
</div>
Para verificar se funcionou, use:
=== "Linux, macOS, Windows Bash"
<div class="termy">
```console
$ which pip
some/directory/fastapi/env/bin/pip
```
</div>
=== "Windows PowerShell"
<div class="termy">
```console
$ Get-Command pip
some/directory/fastapi/env/bin/pip
```
</div>
Se ele exibir o binário `pip` em `env/bin/pip` então funcionou. 🎉
!!! tip
Toda vez que você instalar um novo pacote com `pip` nesse ambiente, ative o ambiente novamente.
Isso garante que se você usar um programa instalado por aquele pacote (como `flit`), você utilizará aquele de seu ambiente local e não outro que possa estar instalado globalmente.
### Flit
**FastAPI** utiliza <a href="https://flit.readthedocs.io/en/latest/index.html" class="external-link" target="_blank">Flit</a> para construir, empacotar e publicar o projeto.
Após ativar o ambiente como descrito acima, instale o `flit`:
<div class="termy">
```console
$ pip install flit
---> 100%
```
</div>
Ative novamente o ambiente para ter certeza que você esteja utilizando o `flit` que você acabou de instalar (e não um global).
E agora use `flit` para instalar as dependências de desenvolvimento:
=== "Linux, macOS"
<div class="termy">
```console
$ flit install --deps develop --symlink
---> 100%
```
</div>
=== "Windows"
Se você está no Windows, use `--pth-file` ao invés de `--symlink`:
<div class="termy">
```console
$ flit install --deps develop --pth-file
---> 100%
```
</div>
Isso irá instalar todas as dependências e seu FastAPI local em seu ambiente local.
#### Usando seu FastAPI local
Se você cria um arquivo Python que importa e usa FastAPI, e roda com Python de seu ambiente local, ele irá utilizar o código fonte de seu FastAPI local.
E se você atualizar o código fonte do FastAPI local, como ele é instalado com `--symlink` (ou `--pth-file` no Windows), quando você rodar aquele arquivo Python novamente, ele irá utilizar a nova versão do FastAPI que você acabou de editar.
Desse modo, você não tem que "instalar" sua versão local para ser capaz de testar cada mudança.
### Formato
Tem um arquivo que você pode rodar que irá formatar e limpar todo o seu código:
<div class="termy">
```console
$ bash scripts/format.sh
```
</div>
Ele irá organizar também todos os seus imports.
Para que ele organize os imports corretamente, você precisa ter o FastAPI instalado localmente em seu ambiente, com o comando na seção acima usando `--symlink` (ou `--pth-file` no Windows).
### Formato dos imports
Tem outro _script_ que formata todos os imports e garante que você não tenha imports não utilizados:
<div class="termy">
```console
$ bash scripts/format-imports.sh
```
</div>
Como ele roda um comando após o outro, modificando e revertendo muitos arquivos, ele demora um pouco para concluir, então pode ser um pouco mais fácil utilizar `scripts/format.sh` frequentemente e `scripts/format-imports.sh` somente após "commitar uma branch".
## Documentação
Primeiro, tenha certeza de configurar seu ambiente como descrito acima, isso irá instalar todas as requisições.
A documentação usa <a href="https://www.mkdocs.org/" class="external-link" target="_blank">MkDocs</a>.
E existem ferramentas/_scripts_ extras para controlar as traduções em `./scripts/docs.py`.
!!! tip
Você não precisa ver o código em `./scripts/docs.py`, você apenas o utiliza na linha de comando.
Toda a documentação está no formato Markdown no diretório `./docs/pt/`.
Muitos dos tutoriais tem blocos de código.
Na maioria dos casos, esse blocos de código são aplicações completas que podem ser rodadas do jeito que estão apresentados.
De fato, esses blocos de código não estão escritos dentro do Markdown, eles são arquivos Python dentro do diretório `./docs_src/`.
E esses arquivos Python são incluídos/injetados na documentação quando se gera o site.
### Testes para Documentação
A maioria dos testes na verdade rodam encima dos arquivos fonte na documentação.
Isso ajuda a garantir:
* Que a documentação esteja atualizada.
* Que os exemplos da documentação possam ser rodadas do jeito que estão apresentadas.
* A maior parte dos recursos é coberta pela documentação, garantida por cobertura de testes.
Durante o desenvolvimento local, existe um _script_ que constrói o site e procura por quaisquer mudanças, carregando na hora:
<div class="termy">
```console
$ python ./scripts/docs.py live
<span style="color: green;">[INFO]</span> Serving on http://127.0.0.1:8008
<span style="color: green;">[INFO]</span> Start watching changes
<span style="color: green;">[INFO]</span> Start detecting changes
```
</div>
Isso irá servir a documentação em `http://127.0.0.1:8008`.
Desse jeito, você poderá editar a documentação/arquivos fonte e ver as mudanças na hora.
#### Typer CLI (opcional)
As instruções aqui mostram como utilizar _scripts_ em `./scripts/docs.py` com o programa `python` diretamente.
Mas você pode usar também <a href="https://typer.tiangolo.com/typer-cli/" class="external-link" target="_blank">Typer CLI</a>, e você terá auto-completação para comandos no seu terminal após instalar o _completion_.
Se você instalou Typer CLI, você pode instalar _completion_ com:
<div class="termy">
```console
$ typer --install-completion
zsh completion installed in /home/user/.bashrc.
Completion will take effect once you restart the terminal.
```
</div>
### Aplicações e documentação ao mesmo tempo
Se você rodar os exemplos com, por exemplo:
<div class="termy">
```console
$ uvicorn tutorial001:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
como Uvicorn utiliza por padrão a porta `8000`, a documentação na porta `8008` não dará conflito.
### Traduções
Ajuda com traduções É MUITO apreciada! E essa tarefa não pode ser concluída sem a ajuda da comunidade. 🌎 🚀
Aqui estão os passos para ajudar com as traduções.
#### Dicas e orientações
* Verifique sempre os <a href="https://github.com/tiangolo/fastapi/pulls" class="external-link" target="_blank">_pull requests_ existentes</a> para a sua linguagem e faça revisões das alterações e aprove elas.
!!! tip
Você pode <a href="https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request" class="external-link" target="_blank">adicionar comentários com sugestões de alterações</a> para _pull requests_ existentes.
Verifique as documentações sobre <a href="https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-request-reviews" class="external-link" target="_blank">adicionar revisão ao _pull request_</a> para aprovação ou solicitação de alterações.
* Verifique em <a href="https://github.com/tiangolo/fastapi/issues" class="external-link" target="_blank">_issues_</a> para ver se existe alguém coordenando traduções para a sua linguagem.
* Adicione um único _pull request_ por página traduzida. Isso tornará muito mais fácil a revisão para as outras pessoas.
Para as linguagens que eu não falo, vou esperar por várias pessoas revisarem a tradução antes de _mergear_.
* Você pode verificar também se há traduções para sua linguagem e adicionar revisão para elas, isso irá me ajudar a saber que a tradução está correta e eu possa _mergear_.
* Utilize os mesmos exemplos Python e somente traduza o texto na documentação. Você não tem que alterar nada no código para que funcione.
* Utilize as mesmas imagens, nomes de arquivo e links. Você não tem que alterar nada disso para que funcione.
* Para verificar o código de duas letras para a linguagem que você quer traduzir, você pode usar a <a href="https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes" class="external-link" target="_blank">Lista de códigos ISO 639-1</a>.
#### Linguagem existente
Vamos dizer que você queira traduzir uma página para uma linguagem que já tenha traduções para algumas páginas, como o Espanhol.
No caso do Espanhol, o código de duas letras é `es`. Então, o diretório para traduções em Espanhol está localizada em `docs/es/`.
!!! tip
A principal ("oficial") linguagem é o Inglês, localizado em `docs/en/`.
Agora rode o _servidor ao vivo_ para as documentações em Espanhol:
<div class="termy">
```console
// Use o comando "live" e passe o código da linguagem como um argumento de linha de comando
$ python ./scripts/docs.py live es
<span style="color: green;">[INFO]</span> Serving on http://127.0.0.1:8008
<span style="color: green;">[INFO]</span> Start watching changes
<span style="color: green;">[INFO]</span> Start detecting changes
```
</div>
Agora você pode ir em <a href="http://127.0.0.1:8008" class="external-link" target="_blank">http://127.0.0.1:8008</a> e ver suas mudanças ao vivo.
Se você procurar no site da documentação do FastAPI, você verá que toda linguagem tem todas as páginas. Mas algumas páginas não estão traduzidas e tem notificação sobre a falta da tradução.
Mas quando você rodar localmente como descrito acima, você somente verá as páginas que já estão traduzidas.
Agora vamos dizer que você queira adicionar uma tradução para a seção [Recursos](features.md){.internal-link target=_blank}.
* Copie o arquivo em:
```
docs/en/docs/features.md
```
* Cole ele exatamente no mesmo local mas para a linguagem que você quer traduzir, por exemplo:
```
docs/es/docs/features.md
```
!!! tip
Observe que a única mudança na rota é o código da linguagem, de `en` para `es`.
* Agora abra o arquivo de configuração MkDocs para Inglês em:
```
docs/en/docs/mkdocs.yml
```
* Procure o lugar onde `docs/features.md` está localizado no arquivo de configuração. Algum lugar como:
```YAML hl_lines="8"
site_name: FastAPI
# Mais coisas
nav:
- FastAPI: index.md
- Languages:
- en: /
- es: /es/
- features.md
```
* Abra o arquivo de configuração MkDocs para a linguagem que você está editando, por exemplo:
```
docs/es/docs/mkdocs.yml
```
* Adicione no mesmo local que está no arquivo em Inglês, por exemplo:
```YAML hl_lines="8"
site_name: FastAPI
# Mais coisas
nav:
- FastAPI: index.md
- Languages:
- en: /
- es: /es/
- features.md
```
Tenha certeza que se existem outras entradas, a nova entrada com sua tradução esteja exatamente na mesma ordem como na versão em Inglês.
Se você for no seu navegador verá que agora a documentação mostra sua nova seção. 🎉
Agora você poderá traduzir tudo e ver como está toda vez que salva o arquivo.
#### Nova linguagem
Vamos dizer que você queira adicionar traduções para uma linguagem que ainda não foi traduzida, nem sequer uma página.
Vamos dizer que você queira adicionar tradução para Haitiano, e ainda não tenha na documentação.
Verificando o link acima, o código para "Haitiano" é `ht`.
O próximo passo é rodar o _script_ para gerar um novo diretório de tradução:
<div class="termy">
```console
// Use o comando new-lang, passe o código da linguagem como um argumento de linha de comando
$ python ./scripts/docs.py new-lang ht
Successfully initialized: docs/ht
Updating ht
Updating en
```
</div>
Agora você pode verificar em seu editor de código o mais novo diretório criado `docs/ht/`.
!!! tip
Crie um primeiro _pull request_ com apenas isso, para iniciar a configuração da nova linguagem, antes de adicionar traduções.
Desse modo outros poderão ajudar com outras páginas enquanto você trabalha na primeira. 🚀
Inicie traduzindo a página principal, `docs/ht/index.md`.
Então você pode continuar com as instruções anteriores, para uma "Linguagem Existente".
##### Nova linguagem não suportada
Se quando rodar o _script_ do _servidor ao vivo_ você pega um erro sobre linguagem não suportada, alguma coisa como:
```
raise TemplateNotFound(template)
jinja2.exceptions.TemplateNotFound: partials/language/xx.html
```
Isso significa que o tema não suporta essa linguagem (nesse caso, com um código falso de duas letras `xx`).
Mas não se preocupe, você pode configurar o tema de linguagem para Inglês e então traduzir o conteúdo da documentação.
Se você precisar fazer isso, edite o `mkdocs.yml` para sua nova linguagem, teremos algo como:
```YAML hl_lines="5"
site_name: FastAPI
# Mais coisas
theme:
# Mais coisas
language: xx
```
Altere essa linguagem de `xx` (do seu código de linguagem) para `en`.
Então você poderá iniciar novamente o _servidor ao vivo_.
#### Pré-visualize o resultado
Quando você usa o _script_ em `./scripts/docs.py` com o comando `live` ele somente exibe os arquivos e traduções disponíveis para a linguagem atual.
Mas uma vez que você tenha concluído, você poderá testar tudo como se parecesse _online_.
Para fazer isso, primeiro construa toda a documentação:
<div class="termy">
```console
// Use o comando "build-all", isso leverá um tempinho
$ python ./scripts/docs.py build-all
Updating es
Updating en
Building docs for: en
Building docs for: es
Successfully built docs for: es
Copying en index.md to README.md
```
</div>
Isso gera toda a documentação em `./docs_build/` para cada linguagem. Isso inclui a adição de quaisquer arquivos com tradução faltando, com uma nota dizendo que "esse arquivo ainda não tem tradução". Mas você não tem que fazer nada com esse diretório.
Então ele constrói todos aqueles _sites_ independentes MkDocs para cada linguagem, combina eles, e gera a saída final em `./site/`.
Então você poderá "servir" eles com o comando `serve`:
<div class="termy">
```console
// Use o comando "serve" após rodar "build-all"
$ python ./scripts/docs.py serve
Warning: this is a very simple server. For development, use mkdocs serve instead.
This is here only to preview a site with translations already built.
Make sure you run the build-all command first.
Serving at: http://127.0.0.1:8008
```
</div>
## Testes
Tem um _script_ que você pode rodar localmente para testar todo o código e gerar relatórios de cobertura em HTML:
<div class="termy">
```console
$ bash scripts/test-cov-html.sh
```
</div>
Esse comando gera um diretório `./htmlcov/`, se você abrir o arquivo `./htmlcov/index.html` no seu navegador, poderá explorar interativamente as regiões de código que estão cobertas pelos testes, e observar se existe alguma região faltando.
### Testes no seu editor
Se você quer usar os testes integrados em seu editor adicione `./docs_src` na sua variável `PYTHONPATH`.
Por exemplo, no VS Code você pode criar um arquivo `.env` com:
```env
PYTHONPATH=./docs_src
```

View File

@@ -0,0 +1,48 @@
# Corpo - Campos
Da mesma forma que você pode declarar validações adicionais e metadados nos parâmetros de *funções de operações de rota* com `Query`, `Path` e `Body`, você pode declarar validações e metadados dentro de modelos do Pydantic usando `Field` do Pydantic.
## Importe `Field`
Primeiro, você tem que importá-lo:
```Python hl_lines="4"
{!../../../docs_src/body_fields/tutorial001.py!}
```
!!! warning "Aviso"
Note que `Field` é importado diretamente do `pydantic`, não do `fastapi` como todo o resto (`Query`, `Path`, `Body`, etc).
## Declare atributos do modelo
Você pode então utilizar `Field` com atributos do modelo:
```Python hl_lines="11-14"
{!../../../docs_src/body_fields/tutorial001.py!}
```
`Field` funciona da mesma forma que `Query`, `Path` e `Body`, ele possui todos os mesmos parâmetros, etc.
!!! note "Detalhes técnicos"
Na realidade, `Query`, `Path` e outros que você verá em seguida, criam objetos de subclasses de uma classe `Param` comum, que é ela mesma uma subclasse da classe `FieldInfo` do Pydantic.
E `Field` do Pydantic retorna uma instância de `FieldInfo` também.
`Body` também retorna objetos de uma subclasse de `FieldInfo` diretamente. E tem outras que você verá mais tarde que são subclasses da classe `Body`.
Lembre-se que quando você importa `Query`, `Path`, e outros de `fastapi`, esse são na realidade funções que retornam classes especiais.
!!! tip "Dica"
Note como cada atributo do modelo com um tipo, valor padrão e `Field` possuem a mesma estrutura que parâmetros de *funções de operações de rota*, com `Field` ao invés de `Path`, `Query` e `Body`.
## Adicione informações extras
Você pode declarar informação extra em `Field`, `Query`, `Body`, etc. E isso será incluído no JSON Schema gerado.
Você irá aprender mais sobre adicionar informações extras posteriormente nessa documentação, quando estiver aprendendo a declarar exemplos.
## Recapitulando
Você pode usar `Field` do Pydantic para declarar validações extras e metadados para atributos do modelo.
Você também pode usar os argumentos de palavras-chave extras para passar metadados do JSON Schema adicionais.

View File

@@ -41,6 +41,7 @@ nav:
- en: /
- es: /es/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
@@ -55,6 +56,7 @@ nav:
- Tutorial - Guia de Usuário:
- tutorial/index.md
- tutorial/first-steps.md
- tutorial/body-fields.md
- alternatives.md
- history-design-future.md
- external-links.md
@@ -98,6 +100,8 @@ extra:
name: es - español
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/

View File

@@ -41,6 +41,7 @@ nav:
- en: /
- es: /es/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
@@ -90,6 +91,8 @@ extra:
name: es - español
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/

View File

@@ -41,6 +41,7 @@ nav:
- en: /
- es: /es/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
@@ -90,6 +91,8 @@ extra:
name: es - español
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/

View File

@@ -41,6 +41,7 @@ nav:
- en: /
- es: /es/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
@@ -90,6 +91,8 @@ extra:
name: es - español
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/

View File

@@ -41,6 +41,7 @@ nav:
- en: /
- es: /es/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
@@ -90,6 +91,8 @@ extra:
name: es - español
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/

View File

@@ -0,0 +1,165 @@
# FastAPI 社区
FastAPI 有一个非常棒的社区,它欢迎来自各个领域和背景的朋友。
## 创建者 & 维护者
嘿! 👋
这就是我:
{% if people %}
<div class="user-list user-list-center">
{% for user in people.maintainers %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Answers: {{ user.answers }}</div><div class="count">Pull Requests: {{ user.prs }}</div></div>
{% endfor %}
</div>
{% endif %}
我是 **FastAPI** 的创建者和维护者. 你能在 [帮助 FastAPI - 获取帮助 - 与作者联系](help-fastapi.md#connect-with-the-author){.internal-link target=_blank} 阅读有关此内容的更多信息。
...但是在这里我想向您展示社区。
---
**FastAPI** 得到了社区的大力支持。因此我想突出他们的贡献。
这些人:
* [帮助他人解决 GitHub 的 issues](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank}。
* [创建 Pull Requests](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}。
* 审核 Pull Requests 对于 [翻译](contributing.md#translations){.internal-link target=_blank} 尤为重要。
向他们致以掌声。 👏 🙇
## 上个月最活跃的用户
上个月这些用户致力于 [帮助他人解决 GitHub 的 issues](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank}。
{% if people %}
<div class="user-list user-list-center">
{% for user in people.last_month_active %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Issues replied: {{ user.count }}</div></div>
{% endfor %}
</div>
{% endif %}
## 专家组
以下是 **FastAPI 专家**。 🤓
这些用户一直以来致力于 [帮助他人解决 GitHub 的 issues](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank}。
他们通过帮助许多人而被证明是专家。✨
{% if people %}
<div class="user-list user-list-center">
{% for user in people.experts %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Issues replied: {{ user.count }}</div></div>
{% endfor %}
</div>
{% endif %}
## 杰出贡献者
以下是 **杰出的贡献者**。 👷
这些用户 [创建了最多已被合并的 Pull Requests](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}。
他们贡献了源代码,文档,翻译等。 📦
{% if people %}
<div class="user-list user-list-center">
{% for user in people.top_contributors %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Pull Requests: {{ user.count }}</div></div>
{% endfor %}
</div>
{% endif %}
还有很多其他贡献者超过100个你可以在 <a href="https://github.com/tiangolo/fastapi/graphs/contributors" class="external-link" target="_blank">FastAPI GitHub 贡献者页面</a> 中看到他们。👷
## 杰出审核者
以下用户是「杰出的评审者」。 🕵️
### 翻译审核
我只会说少数几种语言(而且还不是很流利 😅)。所以,具备[能力去批准文档翻译](contributing.md#translations){.internal-link target=_blank} 是这些评审者们。如果没有它们,就不会有多语言文档。
---
**杰出的评审者** 🕵️ 评审了最多来自他人的 Pull Requests他们保证了代码、文档尤其是 **翻译** 的质量。
{% if people %}
<div class="user-list user-list-center">
{% for user in people.top_reviewers %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Reviews: {{ user.count }}</div></div>
{% endfor %}
</div>
{% endif %}
## 赞助商
以下是 **赞助商** 。😎
他们主要通过<a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub Sponsors</a>支持我在 **FastAPI** (和其他项目)的工作。
### 金牌赞助商
{% if sponsors %} {% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
{% endfor %} {% endif %}
### 银牌赞助商
{% if sponsors %} {% for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
{% endfor %} {% endif %}
{% if people %} {% if people.sponsors_50 %}
### 铜牌赞助商
<div class="user-list user-list-center">
{% for user in people.sponsors_50 %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a></div>
{% endfor %}
</div>
{% endif %} {% endif %}
### 个人赞助
{% if people %}
<div class="user-list user-list-center">
{% for user in people.sponsors %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a></div>
{% endfor %}
</div>
{% endif %}
## 关于数据 - 技术细节
该页面的目的是突出社区为帮助他人而付出的努力。
尤其是那些不引人注目且涉及更困难的任务,例如帮助他人解决问题或者评审翻译 Pull Requests。
该数据每月计算一次,您可以阅读 <a href="https://github.com/tiangolo/fastapi/blob/master/.github/actions/people/app/main.py" class="external-link" target="_blank">源代码</a>。
这里也强调了赞助商的贡献。
我也保留更新算法,栏目,统计阈值等的权利(以防万一🤷)。

View File

@@ -222,13 +222,13 @@ John Doe
假设你有一个名为 `Person` 的类,拥有 name 属性:
```Python hl_lines="1-3"
{!../../../docs_src/python_types/tutorial009.py!}
{!../../../docs_src/python_types/tutorial010.py!}
```
接下来,你可以将一个变量声明为 `Person` 类型:
```Python hl_lines="6"
{!../../../docs_src/python_types/tutorial009.py!}
{!../../../docs_src/python_types/tutorial010.py!}
```
然后,你将再次获得所有的编辑器支持:

View File

@@ -0,0 +1,101 @@
# 请求体 - 更新数据
## 用 `PUT` 更新数据
更新数据请用 <a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/PUT" class="external-link" target="_blank">HTTP `PUT`</a> 操作。
把输入数据转换为以 JSON 格式存储的数据(比如,使用 NoSQL 数据库时),可以使用 `jsonable_encoder`。例如,把 `datetime` 转换为 `str`
```Python hl_lines="30-35"
{!../../../docs_src/body_updates/tutorial001.py!}
```
`PUT` 用于接收替换现有数据的数据。
### 关于更新数据的警告
用 `PUT` 把数据项 `bar` 更新为以下内容时:
```Python
{
"name": "Barz",
"price": 3,
"description": None,
}
```
因为上述数据未包含已存储的属性 `"tax": 20.2`,新的输入模型会把 `"tax": 10.5` 作为默认值。
因此,本次操作把 `tax` 的值「更新」为 `10.5`。
## 用 `PATCH` 进行部分更新
<a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/PATCH" class="external-link" target="_blank">HTTP `PATCH`</a> 操作用于更新 *部分* 数据。
即,只发送要更新的数据,其余数据保持不变。
!!! Note "笔记"
`PATCH` 没有 `PUT` 知名,也怎么不常用。
很多人甚至只用 `PUT` 实现部分更新。
**FastAPI** 对此没有任何限制,可以**随意**互换使用这两种操作。
但本指南也会分别介绍这两种操作各自的用途。
### 使用 Pydantic 的 `exclude_unset` 参数
更新部分数据时,可以在 Pydantic 模型的 `.dict()` 中使用 `exclude_unset` 参数。
比如,`item.dict(exclude_unset=True)`。
这段代码生成的 `dict` 只包含创建 `item` 模型时显式设置的数据,而不包括默认值。
然后再用它生成一个只含已设置(在请求中所发送)数据,且省略了默认值的 `dict`
```Python hl_lines="34"
{!../../../docs_src/body_updates/tutorial002.py!}
```
### 使用 Pydantic 的 `update` 参数
接下来,用 `.copy()` 为已有模型创建调用 `update` 参数的副本,该参数为包含更新数据的 `dict`。
例如,`stored_item_model.copy(update=update_data)`
```Python hl_lines="35"
{!../../../docs_src/body_updates/tutorial002.py!}
```
### 更新部分数据小结
简而言之,更新部分数据应:
* 使用 `PATCH` 而不是 `PUT` (可选,也可以用 `PUT`
* 提取存储的数据;
* 把数据放入 Pydantic 模型;
* 生成不含输入模型默认值的 `dict` (使用 `exclude_unset` 参数);
* 只更新用户设置过的值,不用模型中的默认值覆盖已存储过的值。
* 为已存储的模型创建副本,用接收的数据更新其属性 (使用 `update` 参数)。
* 把模型副本转换为可存入数据库的形式(比如,使用 `jsonable_encoder`)。
* 这种方式与 Pydantic 模型的 `.dict()` 方法类似,但能确保把值转换为适配 JSON 的数据类型,例如, 把 `datetime` 转换为 `str` 。
* 把数据保存至数据库;
* 返回更新后的模型。
```Python hl_lines="30-37"
{!../../../docs_src/body_updates/tutorial002.py!}
```
!!! tip "提示"
实际上HTTP `PUT` 也可以完成相同的操作。
但本节以 `PATCH` 为例的原因是,该操作就是为了这种用例创建的。
!!! note "笔记"
注意,输入模型仍需验证。
因此,如果希望接收的部分更新数据可以省略其他所有属性,则要把模型中所有的属性标记为可选(使用默认值或 `None`)。
为了区分用于**更新**所有可选值的模型与用于**创建**包含必选值的模型,请参照[更多模型](extra-models.md){.internal-link target=_blank} 一节中的思路。

View File

@@ -0,0 +1,289 @@
# 处理错误
某些情况下,需要向客户端返回错误提示。
这里所谓的客户端包括前端浏览器、其他应用程序、物联网设备等。
需要向客户端返回错误提示的场景主要如下:
- 客户端没有执行操作的权限
- 客户端没有访问资源的权限
- 客户端要访问的项目不存在
- 等等 ...
遇到这些情况时,通常要返回 **4XX**400 至 499**HTTP 状态码**。
**4XX** 状态码与表示请求成功的 **2XX**200 至 299 HTTP 状态码类似。
只不过,**4XX** 状态码表示客户端发生的错误。
大家都知道**「404 Not Found」**错误,还有调侃这个错误的笑话吧?
## 使用 `HTTPException`
向客户端返回 HTTP 错误响应,可以使用 `HTTPException`
### 导入 `HTTPException`
```Python hl_lines="1"
{!../../../docs_src/handling_errors/tutorial001.py!}
```
### 触发 `HTTPException`
`HTTPException` 是额外包含了和 API 有关数据的常规 Python 异常。
因为是 Python 异常,所以不能 `return`,只能 `raise`。
如在调用*路径操作函数*里的工具函数时,触发了 `HTTPException`FastAPI 就不再继续执行*路径操作函数*中的后续代码,而是立即终止请求,并把 `HTTPException` 的 HTTP 错误发送至客户端。
在介绍依赖项与安全的章节中,您可以了解更多用 `raise` 异常代替 `return` 值的优势。
本例中,客户端用 `ID` 请求的 `item` 不存在时,触发状态码为 `404` 的异常:
```Python hl_lines="11"
{!../../../docs_src/handling_errors/tutorial001.py!}
```
### 响应结果
请求为 `http://example.com/items/foo``item_id` 为 `「foo」`)时,客户端会接收到 HTTP 状态码 - 200 及如下 JSON 响应结果:
```JSON
{
"item": "The Foo Wrestlers"
}
```
但如果客户端请求 `http://example.com/items/bar``item_id` `「bar」` 不存在时),则会接收到 HTTP 状态码 - 404「未找到」错误及如下 JSON 响应结果:
```JSON
{
"detail": "Item not found"
}
```
!!! tip "提示"
触发 `HTTPException` 时,可以用参数 `detail` 传递任何能转换为 JSON 的值,不仅限于 `str`。
还支持传递 `dict`、`list` 等数据结构。
**FastAPI** 能自动处理这些数据,并将之转换为 JSON。
## 添加自定义响应头
有些场景下要为 HTTP 错误添加自定义响应头。例如,出于某些方面的安全需要。
一般情况下可能不会需要在代码中直接使用响应头。
但对于某些高级应用场景,还是需要添加自定义响应头:
```Python hl_lines="14"
{!../../../docs_src/handling_errors/tutorial002.py!}
```
## 安装自定义异常处理器
添加自定义处理器,要使用 [Starlette 的异常工具](https://www.starlette.io/exceptions/)。
假设要触发的自定义异常叫作 `UnicornException`。
且需要 FastAPI 实现全局处理该异常。
此时,可以用 `@app.exception_handler()` 添加自定义异常控制器:
```Python hl_lines="5-7 13-18 24"
{!../../../docs_src/handling_errors/tutorial003.py!}
```
请求 `/unicorns/yolo` 时,路径操作会触发 `UnicornException`。
但该异常将会被 `unicorn_exception_handler` 处理。
接收到的错误信息清晰明了HTTP 状态码为 `418`JSON 内容如下:
```JSON
{"message": "Oops! yolo did something. There goes a rainbow..."}
```
!!! note "技术细节"
`from starlette.requests import Request` 和 `from starlette.responses import JSONResponse` 也可以用于导入 `Request` 和 `JSONResponse`。
**FastAPI** 提供了与 `starlette.responses` 相同的 `fastapi.responses` 作为快捷方式,但大部分响应操作都可以直接从 Starlette 导入。同理,`Request` 也是如此。
## 覆盖默认异常处理器
**FastAPI** 自带了一些默认异常处理器。
触发 `HTTPException` 或请求无效数据时,这些处理器返回默认的 JSON 响应结果。
不过,也可以使用自定义处理器覆盖默认异常处理器。
### 覆盖请求验证异常
请求中包含无效数据时,**FastAPI** 内部会触发 `RequestValidationError`。
该异常也内置了默认异常处理器。
覆盖默认异常处理器时需要导入 `RequestValidationError`,并用 `@app.excption_handler(RequestValidationError)` 装饰异常处理器。
这样,异常处理器就可以接收 `Request` 与异常。
```Python hl_lines="2 14-16"
{!../../../docs_src/handling_errors/tutorial004.py!}
```
访问 `/items/foo`,可以看到以下内容替换了默认 JSON 错误信息:
```JSON
{
"detail": [
{
"loc": [
"path",
"item_id"
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
```
以下是文本格式的错误信息:
```
1 validation error
path -> item_id
value is not a valid integer (type=type_error.integer)
```
### `RequestValidationError` vs `ValidationError`
!!! warning "警告"
如果您觉得现在还用不到以下技术细节,可以先跳过下面的内容。
`RequestValidationError` 是 Pydantic 的 <a href="https://pydantic-docs.helpmanual.io/#error-handling" class="external-link" target="_blank">`ValidationError`</a> 的子类。
**FastAPI** 调用的就是 `RequestValidationError` 类,因此,如果在 `response_model` 中使用 Pydantic 模型,且数据有错误时,在日志中就会看到这个错误。
但客户端或用户看不到这个错误。反之,客户端接收到的是 HTTP 状态码为 `500` 的「内部服务器错误」。
这是因为在*响应*或代码(不是在客户端的请求里)中出现的 Pydantic `ValidationError` 是代码的 bug。
修复错误时,客户端或用户不能访问错误的内部信息,否则会造成安全隐患。
### 覆盖 `HTTPException` 错误处理器
同理,也可以覆盖 `HTTPException` 处理器。
例如,只为错误返回纯文本响应,而不是返回 JSON 格式的内容:
```Python hl_lines="3-4 9-11 22"
{!../../../docs_src/handling_errors/tutorial004.py!}
```
!!! note "技术细节"
还可以使用 `from starlette.responses import PlainTextResponse`。
**FastAPI** 提供了与 `starlette.responses` 相同的 `fastapi.responses` 作为快捷方式,但大部分响应都可以直接从 Starlette 导入。
### 使用 `RequestValidationError` 的请求体
`RequestValidationError` 包含其接收到的无效数据请求的 `body` 。
开发时,可以用这个请求体生成日志、调试错误,并返回给用户。
```Python hl_lines="14"
{!../../../docs_src/handling_errors/tutorial005.py!}
```
现在试着发送一个无效的 `item`,例如:
```JSON
{
"title": "towel",
"size": "XL"
}
```
收到的响应包含 `body` 信息,并说明数据是无效的:
```JSON hl_lines="12-15"
{
"detail": [
{
"loc": [
"body",
"size"
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
],
"body": {
"title": "towel",
"size": "XL"
}
}
```
### FastAPI `HTTPException` vs Starlette `HTTPException`
**FastAPI** 也提供了自有的 `HTTPException`。
**FastAPI** 的 `HTTPException` 继承自 Starlette 的 `HTTPException` 错误类。
它们之间的唯一区别是,**FastAPI** 的 `HTTPException` 可以在响应中添加响应头。
OAuth 2.0 等安全工具需要在内部调用这些响应头。
因此你可以继续像平常一样在代码中触发 **FastAPI** 的 `HTTPException` 。
但注册异常处理器时,应该注册到来自 Starlette 的 `HTTPException`。
这样做是为了,当 Starlette 的内部代码、扩展或插件触发 Starlette `HTTPException` 时,处理程序能够捕获、并处理此异常。
注意,本例代码中同时使用了这两个 `HTTPException`,此时,要把 Starlette 的 `HTTPException` 命名为 `StarletteHTTPException`
```Python
from starlette.exceptions import HTTPException as StarletteHTTPException
```
### 复用 **FastAPI** 异常处理器
FastAPI 支持先对异常进行某些处理,然后再使用 **FastAPI** 中处理该异常的默认异常处理器。
从 `fastapi.exception_handlers` 中导入要复用的默认异常处理器:
```Python hl_lines="2-5 15 21"
{!../../../docs_src/handling_errors/tutorial006.py!}
```
虽然,本例只是输出了夸大其词的错误信息。
但也足以说明,可以在处理异常之后再复用默认的异常处理器。

View File

@@ -0,0 +1,153 @@
# 请求文件
`File` 用于定义客户端的上传文件。
!!! info "说明"
因为上传文件以「表单数据」形式发送。
所以接收上传文件,要预先安装 <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>。
例如: `pip install python-multipart`
## 导入 `File`
`fastapi` 导入 `File``UploadFile`
```Python hl_lines="1"
{!../../../docs_src/request_files/tutorial001.py!}
```
## 定义 `File` 参数
创建文件(`File`)参数的方式与 `Body` 和 `Form` 一样:
```Python hl_lines="7"
{!../../../docs_src/request_files/tutorial001.py!}
```
!!! info "说明"
`File` 是直接继承自 `Form` 的类。
注意,从 `fastapi` 导入的 `Query`、`Path`、`File` 等项,实际上是返回特定类的函数。
!!! tip "提示"
声明文件体必须使用 `File`否则FastAPI 会把该参数当作查询参数或请求体JSON参数。
文件作为「表单数据」上传。
如果把*路径操作函数*参数的类型声明为 `bytes`**FastAPI** 将以 `bytes` 形式读取和接收文件内容。
这种方式把文件的所有内容都存储在内存里,适用于小型文件。
不过,很多情况下,`UploadFile` 更好用。
## 含 `UploadFile` 的 `File` 参数
定义 `File` 参数时使用 `UploadFile`
```Python hl_lines="12"
{!../../../docs_src/request_files/tutorial001.py!}
```
`UploadFile` 与 `bytes` 相比有更多优势:
* 使用 `spooled` 文件:
* 存储在内存的文件超出最大上限时FastAPI 会把文件存入磁盘;
* 这种方式更适于处理图像、视频、二进制文件等大型文件,好处是不会占用所有内存;
* 可获取上传文件的元数据;
* 自带 <a href="https://docs.python.org/zh-cn/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> `async` 接口;
* 暴露的 Python <a href="https://docs.python.org/zh-cn/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> 对象可直接传递给其他预期「file-like」对象的库。
### `UploadFile`
`UploadFile` 的属性如下:
* `filename`:上传文件名字符串(`str`),例如, `myimage.jpg`
* `content_type`内容类型MIME 类型 / 媒体类型)字符串(`str`),例如,`image/jpeg`
* `file` <a href="https://docs.python.org/zh-cn/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> <a href="https://docs.python.org/zh-cn/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> 对象)。其实就是 Python文件可直接传递给其他预期 `file-like` 对象的函数或支持库。
`UploadFile` 支持以下 `async` 方法,(使用内部 `SpooledTemporaryFile`)可调用相应的文件方法。
* `write(data)`:把 `data` `str` 或 `bytes`)写入文件;
* `read(size)`:按指定数量的字节或字符(`size` (`int`))读取文件内容;
* `seek(offset)`:移动至文件 `offset` `int`)字节处的位置;
* 例如,`await myfile.seek(0) ` 移动到文件开头;
* 执行 `await myfile.read()` 后,需再次读取已读取内容时,这种方法特别好用;
* `close()`:关闭文件。
因为上述方法都是 `async` 方法要搭配「await」使用。
例如,在 `async` *路径操作函数* 内,要用以下方式读取文件内容:
```Python
contents = await myfile.read()
```
在普通 `def` *路径操作函数* 内,则可以直接访问 `UploadFile.file`,例如:
```Python
contents = myfile.file.read()
```
!!! note "`async` 技术细节"
使用 `async` 方法时,**FastAPI** 在线程池中执行文件方法,并 `awiat` 操作完成。
!!! note "Starlette 技术细节"
**FastAPI** 的 `UploadFile` 直接继承自 **Starlette** 的 `UploadFile`,但添加了一些必要功能,使之与 **Pydantic** 及 FastAPI 的其它部件兼容。
## 什么是 「表单数据」
与 JSON 不同HTML 表单(`<form></form>`)向服务器发送数据通常使用「特殊」的编码。
**FastAPI** 要确保从正确的位置读取数据,而不是读取 JSON。
!!! note "技术细节"
不包含文件时,表单数据一般用 `application/x-www-form-urlencoded`「媒体类型」编码。
但表单包含文件时,编码为 `multipart/form-data`。使用了 `File`**FastAPI** 就知道要从请求体的正确位置获取文件。
编码和表单字段详见 <a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> Web 文档的 <code>POST </code></a> 小节。
!!! warning "警告"
可在一个*路径操作*中声明多个 `File` 和 `Form` 参数,但不能同时声明要接收 JSON 的 `Body` 字段。因为此时请求体的编码是 `multipart/form-data`,不是 `application/json`。
这不是 **FastAPI** 的问题,而是 HTTP 协议的规定。
## 多文件上传
FastAPI 支持同时上传多个文件。
可用同一个「表单字段」发送含多个文件的「表单数据」。
上传多个文件时,要声明含 `bytes` 或 `UploadFile` 的列表(`List`
```Python hl_lines="10 15"
{!../../../docs_src/request_files/tutorial002.py!}
```
接收的也是含 `bytes` 或 `UploadFile` 的列表(`list`)。
!!! note "笔记"
注意,截至 2019 年 4 月 14 日Swagger UI 不支持在同一个表单字段中上传多个文件。详见 <a href="https://github.com/swagger-api/swagger-ui/issues/4276" class="external-link" target="_blank">#4276</a> 和 <a href="https://github.com/swagger-api/swagger-ui/issues/3641" class="external-link" target="_blank">#3641</a>.
不过,**FastAPI** 已通过 OpenAPI 标准与之兼容。
因此,只要 Swagger UI 或任何其他支持 OpenAPI 的工具支持多文件上传,都将与 **FastAPI** 兼容。
!!! note "技术细节"
也可以使用 `from starlette.responses import HTMLResponse`。
`fastapi.responses` 其实与 `starlette.responses` 相同,只是为了方便开发者调用。实际上,大多数 **FastAPI** 的响应都直接从 Starlette 调用。
## 小结
本节介绍了如何用 `File` 把上传文件声明为(表单数据的)输入参数。

View File

@@ -0,0 +1,38 @@
# 请求表单与文件
FastAPI 支持同时使用 `File``Form` 定义文件和表单字段。
!!! info "说明"
接收上传文件或表单数据,要预先安装 <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>。
例如,`pip install python-multipart`
## 导入 `File` 与 `Form`
```Python hl_lines="1"
{!../../../docs_src/request_forms_and_files/tutorial001.py!}
```
## 定义 `File` 与 `Form` 参数
创建文件和表单参数的方式与 `Body` 和 `Query` 一样:
```Python hl_lines="8"
{!../../../docs_src/request_forms_and_files/tutorial001.py!}
```
文件和表单字段作为表单数据上传与接收。
声明文件可以使用 `bytes` 或 `UploadFile` 。
!!! warning "警告"
可在一个*路径操作*中声明多个 `File` 与 `Form` 参数,但不能同时声明要接收 JSON 的 `Body` 字段。因为此时请求体的编码为 `multipart/form-data`,不是 `application/json`。
这不是 **FastAPI** 的问题,而是 HTTP 协议的规定。
## 小结
在同一个请求中接收数据和文件时,应同时使用 `File` 和 `Form`。

View File

@@ -0,0 +1,63 @@
# 表单数据
接收的不是 JSON而是表单字段时要使用 `Form`
!!! info "说明"
要使用表单,需预先安装 <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>。
例如,`pip install python-multipart`
## 导入 `Form`
`fastapi` 导入 `Form`
```Python hl_lines="1"
{!../../../docs_src/request_forms/tutorial001.py!}
```
## 定义 `Form` 参数
创建表单(`Form`)参数的方式与 `Body` 和 `Query` 一样:
```Python hl_lines="7"
{!../../../docs_src/request_forms/tutorial001.py!}
```
例如OAuth2 规范的 "密码流" 模式规定要通过表单字段发送 `username` 和 `password`。
<abbr title="specification">该规范</abbr>要求字段必须命名为 `username` 和 `password`,并通过表单字段发送,不能用 JSON。
使用 `Form` 可以声明与 `Body` (及 `Query`、`Path`、`Cookie`)相同的元数据和验证。
!!! info "说明"
`Form` 是直接继承自 `Body` 的类。
!!! tip "提示"
声明表单体要显式使用 `Form` 否则FastAPI 会把该参数当作查询参数或请求体JSON参数。
## 关于 "表单字段"
与 JSON 不同HTML 表单(`<form></form>`)向服务器发送数据通常使用「特殊」的编码。
**FastAPI** 要确保从正确的位置读取数据,而不是读取 JSON。
!!! note "技术细节"
表单数据的「媒体类型」编码一般为 `application/x-www-form-urlencoded`。
但包含文件的表单编码为 `multipart/form-data`。文件处理详见下节。
编码和表单字段详见 <a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> Web 文档的 <code>POST</code></a>小节。
!!! warning "警告"
可在一个*路径操作*中声明多个 `Form` 参数,但不能同时声明要接收 JSON 的 `Body` 字段。因为此时请求体的编码是 `application/x-www-form-urlencoded`,不是 `application/json`。
这不是 **FastAPI** 的问题,而是 HTTP 协议的规定。
## 小结
本节介绍了如何使用 `Form` 声明表单数据输入参数。

View File

@@ -41,6 +41,7 @@ nav:
- en: /
- es: /es/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
@@ -52,6 +53,7 @@ nav:
- uk: /uk/
- zh: /zh/
- features.md
- fastapi-people.md
- python-types.md
- 教程 - 用户指南:
- tutorial/index.md
@@ -72,6 +74,11 @@ nav:
- tutorial/schema-extra-example.md
- tutorial/extra-data-types.md
- tutorial/cookie-params.md
- tutorial/request-forms.md
- tutorial/request-files.md
- tutorial/request-forms-and-files.md
- tutorial/handling-errors.md
- tutorial/body-updates.md
- 安全性:
- tutorial/security/index.md
- tutorial/security/get-current-user.md
@@ -130,6 +137,8 @@ extra:
name: es - español
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/

View File

@@ -5,5 +5,5 @@ app = FastAPI()
@app.get("/typer")
async def read_typer():
async def redirect_typer():
return RedirectResponse("https://typer.tiangolo.com")

View File

@@ -0,0 +1,9 @@
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
app = FastAPI()
@app.get("/fastapi", response_class=RedirectResponse)
async def redirect_fastapi():
return "https://fastapi.tiangolo.com"

View File

@@ -0,0 +1,9 @@
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
app = FastAPI()
@app.get("/pydantic", response_class=RedirectResponse, status_code=302)
async def redirect_pydantic():
return "https://pydantic-docs.helpmanual.io/"

View File

@@ -0,0 +1,10 @@
from fastapi import FastAPI
from fastapi.responses import FileResponse
some_file_path = "large-video-file.mp4"
app = FastAPI()
@app.get("/", response_class=FileResponse)
async def main():
return some_file_path

View File

@@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
__version__ = "0.65.2"
__version__ = "0.66.0"
from starlette import status as status

View File

@@ -206,7 +206,7 @@ class FastAPI(Starlette):
endpoint: Callable[..., Coroutine[Any, Any, Response]],
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -258,7 +258,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -351,7 +351,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -400,7 +400,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -449,7 +449,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -498,7 +498,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -547,7 +547,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -596,7 +596,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -645,7 +645,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -694,7 +694,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,

View File

@@ -36,9 +36,9 @@ def jsonable_encoder(
custom_encoder: Dict[Any, Callable[[Any], Any]] = {},
sqlalchemy_safe: bool = True,
) -> Any:
if include is not None and not isinstance(include, set):
if include is not None and not isinstance(include, (set, dict)):
include = set(include)
if exclude is not None and not isinstance(exclude, set):
if exclude is not None and not isinstance(exclude, (set, dict)):
exclude = set(exclude)
if isinstance(obj, BaseModel):
encoder = getattr(obj.__config__, "json_encoders", {})

View File

@@ -117,6 +117,9 @@ class SchemaBase(BaseModel):
example: Optional[Any] = None
deprecated: Optional[bool] = None
class Config:
extra: str = "allow"
class Schema(SchemaBase):
allOf: Optional[List[SchemaBase]] = None

View File

@@ -1,4 +1,5 @@
import http.client
import inspect
from enum import Enum
from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union, cast
@@ -218,7 +219,19 @@ def get_openapi_path(
)
callbacks[callback.name] = {callback.path: cb_path}
operation["callbacks"] = callbacks
status_code = str(route.status_code)
if route.status_code is not None:
status_code = str(route.status_code)
else:
# It would probably make more sense for all response classes to have an
# explicit default status_code, and to extract it from them, instead of
# doing this inspection tricks, that would probably be in the future
# TODO: probably make status_code a default class attribute for all
# responses in Starlette
response_signature = inspect.signature(current_response_class.__init__)
status_code_param = response_signature.parameters.get("status_code")
if status_code_param is not None:
if isinstance(status_code_param.default, int):
status_code = str(status_code_param.default)
operation.setdefault("responses", {}).setdefault(status_code, {})[
"description"
] = route.response_description

View File

@@ -154,7 +154,7 @@ async def run_endpoint_function(
def get_request_handler(
dependant: Dependant,
body_field: Optional[ModelField] = None,
status_code: int = 200,
status_code: Optional[int] = None,
response_class: Union[Type[Response], DefaultPlaceholder] = Default(JSONResponse),
response_field: Optional[ModelField] = None,
response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
@@ -184,7 +184,9 @@ def get_request_handler(
if body_bytes:
json_body: Any = Undefined
content_type_value = request.headers.get("content-type")
if content_type_value:
if not content_type_value:
json_body = await request.json()
else:
message = email.message.Message()
message["content-type"] = content_type_value
if message.get_content_maintype() == "application":
@@ -230,11 +232,12 @@ def get_request_handler(
exclude_none=response_model_exclude_none,
is_coroutine=is_coroutine,
)
response = actual_response_class(
content=response_data,
status_code=status_code,
background=background_tasks, # type: ignore # in Starlette
)
response_args: Dict[str, Any] = {"background": background_tasks}
# If status_code was set, use it, otherwise use the default from the
# response class, in the case of redirect it's 307
if status_code is not None:
response_args["status_code"] = status_code
response = actual_response_class(response_data, **response_args)
response.headers.raw.extend(sub_response.headers.raw)
if sub_response.status_code:
response.status_code = sub_response.status_code
@@ -291,7 +294,7 @@ class APIRoute(routing.Route):
endpoint: Callable[..., Any],
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -467,7 +470,7 @@ class APIRouter(routing.Router):
endpoint: Callable[..., Any],
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -539,7 +542,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -717,7 +720,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -767,7 +770,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -817,7 +820,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -867,7 +870,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -917,7 +920,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -967,7 +970,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -1017,7 +1020,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -1067,7 +1070,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,

View File

@@ -66,10 +66,10 @@ test = [
]
doc = [
"mkdocs >=1.1.2,<2.0.0",
"mkdocs-material >=6.1.4,<7.0.0",
"markdown-include >=0.5.1,<0.6.0",
"mkdocs-material >=7.1.9,<8.0.0",
"markdown-include >=0.6.0,<0.7.0",
"mkdocs-markdownextradata-plugin >=0.1.7,<0.2.0",
"typer-cli >=0.0.9,<0.0.10",
"typer-cli >=0.0.12,<0.0.13",
"pyyaml >=5.3.1,<6.0.0"
]
dev = [

View File

@@ -0,0 +1,51 @@
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
class Config:
schema_extra = {
"x-something-internal": {"level": 4},
}
@app.get("/foo", response_model=Item)
def foo():
return {"name": "Foo item"}
client = TestClient(app)
item_schema = {
"title": "Item",
"required": ["name"],
"type": "object",
"x-something-internal": {
"level": 4,
},
"properties": {
"name": {
"title": "Name",
"type": "string",
}
},
}
def test_custom_response_schema():
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json()["components"]["schemas"]["Item"] == item_schema
def test_response():
# For coverage
response = client.get("/foo")
assert response.status_code == 200, response.text
assert response.json() == {"name": "Foo item"}

View File

@@ -0,0 +1,174 @@
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel
class Test(BaseModel):
foo: str
bar: str
class Test2(BaseModel):
test: Test
baz: str
class Test3(BaseModel):
name: str
age: int
test2: Test2
app = FastAPI()
@app.get(
"/simple_include",
response_model=Test2,
response_model_include={"baz": ..., "test": {"foo"}},
)
def simple_include():
return Test2(
test=Test(foo="simple_include test foo", bar="simple_include test bar"),
baz="simple_include test2 baz",
)
@app.get(
"/simple_include_dict",
response_model=Test2,
response_model_include={"baz": ..., "test": {"foo"}},
)
def simple_include_dict():
return {
"test": {
"foo": "simple_include_dict test foo",
"bar": "simple_include_dict test bar",
},
"baz": "simple_include_dict test2 baz",
}
@app.get(
"/simple_exclude",
response_model=Test2,
response_model_exclude={"test": {"bar"}},
)
def simple_exclude():
return Test2(
test=Test(foo="simple_exclude test foo", bar="simple_exclude test bar"),
baz="simple_exclude test2 baz",
)
@app.get(
"/simple_exclude_dict",
response_model=Test2,
response_model_exclude={"test": {"bar"}},
)
def simple_exclude_dict():
return {
"test": {
"foo": "simple_exclude_dict test foo",
"bar": "simple_exclude_dict test bar",
},
"baz": "simple_exclude_dict test2 baz",
}
@app.get(
"/mixed",
response_model=Test3,
response_model_include={"test2", "name"},
response_model_exclude={"test2": {"baz"}},
)
def mixed():
return Test3(
name="mixed test3 name",
age=3,
test2=Test2(
test=Test(foo="mixed test foo", bar="mixed test bar"), baz="mixed test2 baz"
),
)
@app.get(
"/mixed_dict",
response_model=Test3,
response_model_include={"test2", "name"},
response_model_exclude={"test2": {"baz"}},
)
def mixed_dict():
return {
"name": "mixed_dict test3 name",
"age": 3,
"test2": {
"test": {"foo": "mixed_dict test foo", "bar": "mixed_dict test bar"},
"baz": "mixed_dict test2 baz",
},
}
client = TestClient(app)
def test_nested_include_simple():
response = client.get("/simple_include")
assert response.status_code == 200, response.text
assert response.json() == {
"baz": "simple_include test2 baz",
"test": {"foo": "simple_include test foo"},
}
def test_nested_include_simple_dict():
response = client.get("/simple_include_dict")
assert response.status_code == 200, response.text
assert response.json() == {
"baz": "simple_include_dict test2 baz",
"test": {"foo": "simple_include_dict test foo"},
}
def test_nested_exclude_simple():
response = client.get("/simple_exclude")
assert response.status_code == 200, response.text
assert response.json() == {
"baz": "simple_exclude test2 baz",
"test": {"foo": "simple_exclude test foo"},
}
def test_nested_exclude_simple_dict():
response = client.get("/simple_exclude_dict")
assert response.status_code == 200, response.text
assert response.json() == {
"baz": "simple_exclude_dict test2 baz",
"test": {"foo": "simple_exclude_dict test foo"},
}
def test_nested_include_mixed():
response = client.get("/mixed")
assert response.status_code == 200, response.text
assert response.json() == {
"name": "mixed test3 name",
"test2": {
"test": {"foo": "mixed test foo", "bar": "mixed test bar"},
},
}
def test_nested_include_mixed_dict():
response = client.get("/mixed_dict")
assert response.status_code == 200, response.text
assert response.json() == {
"name": "mixed_dict test3 name",
"test2": {
"test": {"foo": "mixed_dict test foo", "bar": "mixed_dict test bar"},
},
}

View File

@@ -229,6 +229,20 @@ def test_geo_json():
assert response.status_code == 200, response.text
def test_no_content_type_is_json():
response = client.post(
"/items/",
data='{"name": "Foo", "price": 50.5}',
)
assert response.status_code == 200, response.text
assert response.json() == {
"name": "Foo",
"description": None,
"price": 50.5,
"tax": None,
}
def test_wrong_headers():
data = '{"name": "Foo", "price": 50.5}'
invalid_dict = {

View File

@@ -5,6 +5,32 @@ from docs_src.custom_response.tutorial006 import app
client = TestClient(app)
openapi_schema = {
"openapi": "3.0.2",
"info": {"title": "FastAPI", "version": "0.1.0"},
"paths": {
"/typer": {
"get": {
"summary": "Redirect Typer",
"operationId": "redirect_typer_typer_get",
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
}
},
}
}
},
}
def test_openapi_schema():
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json() == openapi_schema
def test_get():
response = client.get("/typer", allow_redirects=False)
assert response.status_code == 307, response.text

View File

@@ -0,0 +1,32 @@
from fastapi.testclient import TestClient
from docs_src.custom_response.tutorial006b import app
client = TestClient(app)
openapi_schema = {
"openapi": "3.0.2",
"info": {"title": "FastAPI", "version": "0.1.0"},
"paths": {
"/fastapi": {
"get": {
"summary": "Redirect Fastapi",
"operationId": "redirect_fastapi_fastapi_get",
"responses": {"307": {"description": "Successful Response"}},
}
}
},
}
def test_openapi_schema():
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json() == openapi_schema
def test_redirect_response_class():
response = client.get("/fastapi", allow_redirects=False)
assert response.status_code == 307
assert response.headers["location"] == "https://fastapi.tiangolo.com"

View File

@@ -0,0 +1,32 @@
from fastapi.testclient import TestClient
from docs_src.custom_response.tutorial006c import app
client = TestClient(app)
openapi_schema = {
"openapi": "3.0.2",
"info": {"title": "FastAPI", "version": "0.1.0"},
"paths": {
"/pydantic": {
"get": {
"summary": "Redirect Pydantic",
"operationId": "redirect_pydantic_pydantic_get",
"responses": {"302": {"description": "Successful Response"}},
}
}
},
}
def test_openapi_schema():
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json() == openapi_schema
def test_redirect_status_code():
response = client.get("/pydantic", allow_redirects=False)
assert response.status_code == 302
assert response.headers["location"] == "https://pydantic-docs.helpmanual.io/"

View File

@@ -0,0 +1,17 @@
from pathlib import Path
from fastapi.testclient import TestClient
from docs_src.custom_response import tutorial009
from docs_src.custom_response.tutorial009 import app
client = TestClient(app)
def test_get(tmp_path: Path):
file_path: Path = tmp_path / "large-video-file.mp4"
tutorial009.some_file_path = str(file_path)
test_content = b"Fake video bytes"
file_path.write_bytes(test_content)
response = client.get("/")
assert response.content == test_content

View File

@@ -0,0 +1,17 @@
from pathlib import Path
from fastapi.testclient import TestClient
from docs_src.custom_response import tutorial009b
from docs_src.custom_response.tutorial009b import app
client = TestClient(app)
def test_get(tmp_path: Path):
file_path: Path = tmp_path / "large-video-file.mp4"
tutorial009b.some_file_path = str(file_path)
test_content = b"Fake video bytes"
file_path.write_bytes(test_content)
response = client.get("/")
assert response.content == test_content