Compare commits

..

148 Commits

Author SHA1 Message Date
Sebastián Ramírez
b890bd1dc5 🔖 Release version 0.65.0 2021-05-10 17:45:21 +02:00
github-actions
3819a11b5f 📝 Update release notes 2021-05-10 14:09:42 +00:00
Hannes Küttner
4aed0411e9 ⬆️ Upgrade Starlette to 0.14.2, including internal UJSONResponse migrated from Starlette (#2335) 2021-05-10 16:09:04 +02:00
github-actions
04ac466748 📝 Update release notes 2021-05-10 08:11:22 +00:00
Sebastián Ramírez
d75126a4ce 👷 Add GitHub Action cache to speed up CI installs (#3204) 2021-05-10 10:10:48 +02:00
github-actions
c654e8384b 📝 Update release notes 2021-05-10 07:47:11 +00:00
Sebastián Ramírez
7c9d0168ff ⬆️ Upgrade setup-python GitHub Action to v2 (#3203) 2021-05-10 09:46:32 +02:00
github-actions
e956ba4d4a 📝 Update release notes 2021-05-10 07:27:43 +00:00
neternefer
85b32f51ff 🌐 Initialize new language Polish for translations (#3170)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-05-10 09:27:07 +02:00
github-actions
08fabb7b2e 📝 Update release notes 2021-05-10 07:16:15 +00:00
Sebastián Ramírez
273b2cd646 🐛 Fix docs script to generate a new translation language with overrides boilerplate (#3202) 2021-05-10 09:15:39 +02:00
github-actions
de1a5125f8 📝 Update release notes 2021-05-08 17:51:32 +00:00
Sebastián Ramírez
da86791224 Add new Deta banner badge with new sponsorship tier 🙇 (#3194) 2021-05-08 19:50:56 +02:00
Sebastián Ramírez
c646eaa6bb ✏️ Fix typo/order in release notes 2021-05-07 14:25:21 +02:00
github-actions
bf44b428dd 📝 Update release notes 2021-05-07 12:19:57 +00:00
github-actions[bot]
c2907b189c 👥 Update FastAPI People (#3189)
Co-authored-by: github-actions <github-actions@github.com>
2021-05-07 14:19:19 +02:00
github-actions
75317d230b 📝 Update release notes 2021-05-07 12:05:45 +00:00
Sebastián Ramírez
e662654c49 🔊 Update FastAPI People to allow better debugging (#3188) 2021-05-07 14:04:54 +02:00
Sebastián Ramírez
2a67321130 🔖 Release version 0.64.0 2021-05-07 10:15:26 +02:00
Sebastián Ramírez
8d9d2c0d3f 📝 Update release notes 2021-05-07 10:14:21 +02:00
github-actions
dc6a78c357 📝 Update release notes 2021-05-06 15:48:23 +00:00
T
73d1def114 📝 Add link to article in Russian "FastAPI: знакомимся с фреймворком" (#2564) 2021-05-06 17:47:49 +02:00
github-actions
3dc74ba29f 📝 Update release notes 2021-05-06 15:42:53 +00:00
dompatmore
d9d6031db5 📝 Add external link to blog post "Authenticate Your FastAPI App with Auth0" (#2172)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-05-06 17:42:14 +02:00
Sebastián Ramírez
6135417789 📝 Update release notes 2021-05-06 17:32:04 +02:00
github-actions
6d138f218b 📝 Update release notes 2021-05-05 18:21:32 +00:00
Austin Orr
e10a4375f9 Add support for adding multiple examples in request bodies and path, query, cookie, and header params (#1267)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-05-05 20:20:56 +02:00
github-actions
3e32eb55f0 📝 Update release notes 2021-05-04 09:03:02 +00:00
NiJia Lin
b3f139c0d9 🌐 Fix Chinese translation of Tutorial - Query Parameters, remove obsolete content (#3051) 2021-05-04 11:02:19 +02:00
github-actions
3b4c692534 📝 Update release notes 2021-05-04 09:01:17 +00:00
Sam Courtemanche
05c859f324 🌐 Add French translation for Tutorial - Background Tasks (#3098)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-05-04 11:00:43 +02:00
github-actions
48a33b0453 📝 Update release notes 2021-05-04 08:49:43 +00:00
SueNaeunYang
70746a7bf0 🌐 Fix Korean translation for docs/ko/docs/index.md (#3159) 2021-05-04 10:49:07 +02:00
github-actions
69e3c6e3d3 📝 Update release notes 2021-05-04 08:38:41 +00:00
Spike
388e5c0c25 🌐 Add Korean translation for Tutorial - Query Parameters (#2390)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-05-04 10:38:02 +02:00
github-actions
61db5ebcc2 📝 Update release notes 2021-05-04 08:28:21 +00:00
JulianMaurin
23845979ea 🌐 Add French translation for FastAPI People (#2232)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-05-04 10:27:49 +02:00
github-actions
83f7a36d05 📝 Update release notes 2021-05-04 08:25:39 +00:00
Spike
462014e296 🌐 Add Korean translation for Tutorial - Path Parameters (#2355) 2021-05-04 10:24:58 +02:00
github-actions
5da5ae5554 📝 Update release notes 2021-05-04 08:20:03 +00:00
Jérôme Fink
f3a985cb81 🌐 Add French translation for Features (#2157)
Co-authored-by: Jérôme Fink <jerome.fink@unamur.be>
2021-05-04 10:19:24 +02:00
github-actions
22528373bb 📝 Update release notes 2021-04-07 07:04:13 +00:00
github-actions[bot]
ce0ec06e8a 👥 Update FastAPI People (#3031)
Co-authored-by: github-actions <github-actions@github.com>
2021-04-07 09:03:39 +02:00
github-actions
10397ddc30 📝 Update release notes 2021-03-27 17:52:30 +00:00
Shucai.wang
6f72a27632 🌐 Add Chinese translation for Tutorial - Debugging (#2737)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-03-27 18:51:51 +01:00
Sebastián Ramírez
2783667f80 📝 Update release notes 2021-03-27 18:50:39 +01:00
github-actions
d8c1d040d4 📝 Update release notes 2021-03-27 17:39:13 +00:00
Xie Wei
7f037f1bdc 🌐 Add Chinese translation for Tutorial - Security - OAuth2 with Password (and hashing), Bearer with JWT tokens (#2642)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-03-27 18:38:33 +01:00
github-actions
f31104585f 📝 Update release notes 2021-03-27 17:36:52 +00:00
mode
5934a75ddd 🌐 Add Korean translation for Tutorial - Header Parameters (#2589)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-03-27 18:36:09 +01:00
github-actions
650abf091b 📝 Update release notes 2021-03-27 17:31:54 +00:00
Shucai.wang
66f18e9282 🌐 Add Chinese translation for Tutorial - Metadata and Docs URLs (#2559) 2021-03-27 18:31:11 +01:00
github-actions
f044f13121 📝 Update release notes 2021-03-27 17:30:24 +00:00
Spike
0250cfa398 🌐 Add Korean translation for Tutorial - First Steps (#2323)
Co-authored-by: Dahun Jeong <gnsgnsek@gmail.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-03-27 18:29:45 +01:00
github-actions
f4ce2510f3 📝 Update release notes 2021-03-27 17:28:52 +00:00
Shucai.wang
8f0a604a37 🌐 Add Chinese translation for Tutorial - CORS (Cross-Origin Resource Sharing) (#2540)
Co-authored-by: Xie Wei <ampedee@gmail.com>
2021-03-27 18:28:07 +01:00
github-actions
0f4c2b6ee0 📝 Update release notes 2021-03-27 17:26:01 +00:00
lpdswing
368d314e11 🌐 Add Chinese translation for Tutorial - Middleware (#2334)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-03-27 18:25:21 +01:00
github-actions
4e79cb0be4 📝 Update release notes 2021-03-27 17:23:26 +00:00
Spike
973595b3cb 🌐 Add Korean translation for Tutorial - Intro (#2317)
Co-authored-by: Dahun Jeong <gnsgnsek@gmail.com>
2021-03-27 18:22:50 +01:00
github-actions
fa779017d2 📝 Update release notes 2021-03-27 16:55:48 +00:00
Sebastián Ramírez
b2e27de2fc 🔧 Update top banner, point to newsletter (#3003) 2021-03-27 17:55:12 +01:00
github-actions
31a7bfd227 📝 Update release notes 2021-03-27 16:46:10 +00:00
Sebastián Ramírez
47dde41c6c 🔧 Disable sponsor WeTransfer (#3002) 2021-03-27 17:45:32 +01:00
github-actions
413a86998e 📝 Update release notes 2021-03-27 16:36:52 +00:00
Sebastián Ramírez
36721d4362 📌 Pin SQLAlchemy range, as it doesn't use SemVer (#3001) 2021-03-27 17:36:07 +01:00
github-actions
c09e950bd2 📝 Update release notes 2021-03-01 19:02:33 +00:00
Sebastián Ramírez
4d208b2b90 🎨 Add newly required type annotations for mypy (#2882)
* ⬆️ Upgrade mypy

* 🎨 Add extra type annotations, now required by mypy
2021-03-01 20:01:50 +01:00
github-actions
071c6a17dd 📝 Update release notes 2021-03-01 18:33:53 +00:00
github-actions[bot]
4ab79c679b 👥 Update FastAPI People (#2880)
Co-authored-by: github-actions <github-actions@github.com>
2021-03-01 19:33:08 +01:00
github-actions
33be5fc8ba 📝 Update release notes 2021-02-07 18:27:26 +00:00
Davide Fiocco
a7a353e1f5 📝 Fix broken link to article: Machine learning model serving in Python using FastAPI and Streamlit (#2557) 2021-02-07 19:26:44 +01:00
github-actions
c153d9b83e 📝 Update release notes 2021-02-07 18:26:07 +00:00
vjanz
2875d88ccf 📝 Add FastAPI Medium Article: Deploy a dockerized FastAPI application to AWS (#2515)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-02-07 19:25:27 +01:00
github-actions
9e0cca828d 📝 Update release notes 2021-02-07 18:19:21 +00:00
johnthagen
5dc3ec4a65 ✏ Fix typo in Tutorial - Handling Errors (#2486) 2021-02-07 19:18:37 +01:00
github-actions
bda392cba6 📝 Update release notes 2021-02-07 18:16:26 +00:00
water_lift
f22137346a 🎨 Remove internal "type: ignore", now unnecessary (#2424) 2021-02-07 19:15:43 +01:00
github-actions
f108741a82 📝 Update release notes 2021-02-07 18:14:23 +00:00
Jürgen Gmach
8433e8efe2 ✏ Fix typo in Security OAuth2 scopes (#2407) 2021-02-07 19:13:41 +01:00
github-actions
e6a1a9e193 📝 Update release notes 2021-02-07 18:06:49 +00:00
kangni
bbb22813e6 ✏ Fix typo/clarify docs for SQL (Relational) Databases (#2393)
By way of code example, I think this is a typo. btw, the tutorial is very well written.
2021-02-07 19:06:08 +01:00
github-actions
f0f8e287ec 📝 Update release notes 2021-02-07 18:02:41 +00:00
Xie Wei
0af6cbe990 🌐 Add Chinese translation for Tutorial - Bigger Applications - Multiple Files (#2453)
Co-authored-by: Shucai.wang <blt23@126.com>
2021-02-07 19:02:00 +01:00
github-actions
9e9e068762 📝 Update release notes 2021-02-07 18:01:12 +00:00
Xie Wei
9fda0149da 🌐 Add Chinese translation for Tutorial - Security - Security Intro (#2443) 2021-02-07 19:00:14 +01:00
github-actions
95a713b3e2 📝 Update release notes 2021-02-07 17:59:55 +00:00
maoyibo
2da3d62d37 🌐 Add Chinese translation for Tutorial - Header Parameters (#2412)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-02-07 18:59:12 +01:00
github-actions
7dd2e92d7e 📝 Update release notes 2021-02-07 17:52:50 +00:00
maoyibo
6d06e13284 🌐 Add Chinese translation for Tutorial - Extra Data Types (#2410)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-02-07 18:52:09 +01:00
github-actions
a2199c545b 📝 Update release notes 2021-02-07 17:47:02 +00:00
T. Tokusumi
08cbc6c8ff 🌐 Add Japanese translation for Deployment - Docker (#2312)
Co-authored-by: Taki Komiyama <39375566+komtaki@users.noreply.github.com>
Co-authored-by: Sho Nakamura <sh0nk.developer@gmail.com>
2021-02-07 18:46:22 +01:00
github-actions
f730160037 📝 Update release notes 2021-02-07 17:45:09 +00:00
T. Tokusumi
20360c207e 🌐 Add Japanese translation for Deployment - Versions (#2310)
Co-authored-by: Taki Komiyama <39375566+komtaki@users.noreply.github.com>
Co-authored-by: Sho Nakamura <sh0nk.developer@gmail.com>
2021-02-07 18:44:28 +01:00
github-actions
568a54dff2 📝 Update release notes 2021-02-07 17:43:14 +00:00
Alicrazy
91cacc9c92 🌐 Add Chinese translation for Tutorial - Cookie Parameters (#2261)
Co-authored-by: lijun <lijun@duozhuayu.net>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-02-07 18:42:34 +01:00
github-actions
b3899333f4 📝 Update release notes 2021-02-07 17:41:26 +00:00
Amit Chaudhary
6b6a310e54 📝 Add external link to "FastAPI for Flask Users" (#2280) 2021-02-07 18:40:42 +01:00
github-actions
cb2dce03c0 📝 Update release notes 2021-02-07 17:38:52 +00:00
T. Tokusumi
7122687f25 🌐 Add Japanese translation for Tutorial - Static files (#2260)
Co-authored-by: Taki Komiyama <39375566+komtaki@users.noreply.github.com>
Co-authored-by: Sho Nakamura <sh0nk.developer@gmail.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-02-07 18:38:10 +01:00
github-actions
af6fcf1413 📝 Update release notes 2021-02-07 17:32:12 +00:00
T. Tokusumi
cd8b90a5a4 🌐 Add Japanese translation for Tutorial - Testing (#2259)
Co-authored-by: Taki Komiyama <39375566+komtaki@users.noreply.github.com>
Co-authored-by: Sho Nakamura <sh0nk.developer@gmail.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-02-07 18:31:30 +01:00
github-actions
c88fb2eef0 📝 Update release notes 2021-02-07 17:26:15 +00:00
T. Tokusumi
17781e3596 🌐 Add Japanese translation for Tutorial - Debugging (#2256)
Co-authored-by: Sho Nakamura <sh0nk.developer@gmail.com>
2021-02-07 18:25:31 +01:00
github-actions
a381642558 📝 Update release notes 2021-02-07 17:24:39 +00:00
T. Tokusumi
5828043b69 🌐 Add Japanese translation for Tutorial - Middleware (#2255)
Co-authored-by: Sho Nakamura <sh0nk.developer@gmail.com>
2021-02-07 18:23:55 +01:00
github-actions
909a81f88a 📝 Update release notes 2021-02-07 17:21:27 +00:00
T. Tokusumi
faec713e0d 🌐 Add Japanese translation for Concurrency and async / await (#2058)
Co-authored-by: Taki Komiyama <39375566+komtaki@users.noreply.github.com>
Co-authored-by: Sho Nakamura <sh0nk.developer@gmail.com>
2021-02-07 18:20:43 +01:00
github-actions
60addbcdd5 📝 Update release notes 2021-02-01 14:49:57 +00:00
github-actions[bot]
a27a1bc53c 👥 Update FastAPI People (#2739)
Co-authored-by: github-actions <github-actions@github.com>
2021-02-01 15:49:09 +01:00
github-actions
41f291524d 📝 Update release notes 2021-01-19 20:13:46 +00:00
Sebastián Ramírez
6b3bc7384e 🔧 Add new Gold Sponsor Talk Python 🎉 (#2673) 2021-01-19 21:12:58 +01:00
github-actions
561bbfb5d2 📝 Update release notes 2021-01-18 15:35:35 +00:00
Sebastián Ramírez
8ce1c81398 🔧 Add new Gold Sponsor vim.so 🎉 (#2669) 2021-01-18 16:34:46 +01:00
github-actions
cb40e27db2 📝 Update release notes 2021-01-09 21:24:44 +00:00
Sebastián Ramírez
f031973848 🔧 Add FastAPI user survey banner (#2623)
* 🔧 Add FastAPI user survey banner

* 🔧 Make FastAPI user survey banner open new tab
2021-01-09 22:24:03 +01:00
github-actions
307d37d85c 📝 Update release notes 2021-01-09 21:11:58 +00:00
Sebastián Ramírez
bf290fa5f0 🔧 Add new Bronze Sponsor(s) 🥉🎉 (#2622)
* 🔧 Update FastAPI People sponsors, include new Bronze Sponsor 🎉

* 📝 Update FastAPI People in Japanese
2021-01-09 22:11:15 +01:00
github-actions
26f313d524 📝 Update release notes 2021-01-09 20:55:21 +00:00
Sebastián Ramírez
73021d7261 📝 Update social links: add Discord, fix GitHub (#2621) 2021-01-09 21:54:38 +01:00
github-actions
f54fb88ad5 📝 Update release notes 2021-01-09 19:00:40 +00:00
Xie Wei
b3d2f47bc8 🌐 Add Chinese translation for Tutorial - Security - Simple OAuth2 with Password and Bearer (#2514)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-01-09 19:59:56 +01:00
github-actions
52f170b3fe 📝 Update release notes 2021-01-09 18:59:33 +00:00
T. Tokusumi
9442845ca5 🌐 Add Japanese translation for Deployment - Deta (#2314)
Co-authored-by: Taki Komiyama <39375566+komtaki@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-01-09 19:58:52 +01:00
github-actions
fe31b0caae 📝 Update release notes 2021-01-09 18:53:47 +00:00
Xie Wei
d2ca3df033 🌐 Add Chinese translation for Tutorial - Security - Get Current User (#2474) 2021-01-09 19:53:05 +01:00
github-actions
838ea752b2 📝 Update release notes 2021-01-09 18:52:30 +00:00
T. Tokusumi
2b49b8c70a 🌐 Add Japanese translation for Deployment - Manually (#2313)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-01-09 19:51:42 +01:00
github-actions
05b024d61b 📝 Update release notes 2021-01-09 18:47:49 +00:00
T. Tokusumi
c7742e3c56 🌐 Add Japanese translation for Deployment - Intro (#2309)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-01-09 19:47:08 +01:00
github-actions
4f9104ce97 📝 Update release notes 2021-01-09 18:43:08 +00:00
T. Tokusumi
07a8f7b5b5 🌐 Add Japanese translation for FastAPI People (#2254)
Co-authored-by: Taki Komiyama <39375566+komtaki@users.noreply.github.com>
2021-01-09 19:42:24 +01:00
github-actions
f2a28f4b5b 📝 Update release notes 2021-01-09 18:41:10 +00:00
atsumi
5a4a61ca67 🌐 Add Japanese translation for Advanced - Path Operation Advanced Configuration (#2124)
Co-authored-by: T. Tokusumi <41147016+tokusumi@users.noreply.github.com>
2021-01-09 19:40:27 +01:00
github-actions
71ac76c3cd 📝 Update release notes 2021-01-09 18:39:11 +00:00
T. Tokusumi
68dca8f42d 🌐 Add Japanese translation for External Links (#2070)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-01-09 19:38:20 +01:00
github-actions
a38e6f4e2c 📝 Update release notes 2021-01-09 18:33:53 +00:00
SwftAlpc
ca26f2274c 🌐 Add Japanese translation for Tutorial - Body - Updates (#1956)
Co-authored-by: T. Tokusumi <41147016+tokusumi@users.noreply.github.com>
Co-authored-by: ryusuke.miyaji <bluce826@gmail.com>
Co-authored-by: ryuckel <36391432+ryuckel@users.noreply.github.com>
Co-authored-by: tokusumi <tksmtoms@gmail.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-01-09 19:33:07 +01:00
github-actions
8108cd89bb 📝 Update release notes 2021-01-09 18:28:54 +00:00
SwftAlpc
8560151090 🌐 Add Japanese translation for Tutorial - Form Data (#1943)
Co-authored-by: ryusuke.miyaji <bluce826@gmail.com>
Co-authored-by: ryuckel <36391432+ryuckel@users.noreply.github.com>
Co-authored-by: tokusumi <tksmtoms@gmail.com>
Co-authored-by: T. Tokusumi <41147016+tokusumi@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-01-09 19:28:15 +01:00
github-actions
91805cdf03 📝 Update release notes 2021-01-09 18:20:10 +00:00
SwftAlpc
48cba16578 🌐 Add Japanese translation for Tutorial - Cookie Parameters (#1933)
Co-authored-by: ryusuke.miyaji <bluce826@gmail.com>
Co-authored-by: ryuckel <36391432+ryuckel@users.noreply.github.com>
Co-authored-by: tokusumi <tksmtoms@gmail.com>
Co-authored-by: T. Tokusumi <41147016+tokusumi@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-01-09 19:19:26 +01:00
github-actions
7098e3b150 📝 Update release notes 2021-01-09 16:58:08 +00:00
Sebastián Ramírez
a7cc25eb11 🔧 Update FastAPI People GitHub Sponsors order (#2620) 2021-01-09 17:57:27 +01:00
github-actions
d2eb4a71ee 📝 Update release notes 2021-01-05 21:04:05 +00:00
Sebastián Ramírez
54eeb3161f 🔧 Update InvestSuite sponsor data (#2608) 2021-01-05 22:03:24 +01:00
github-actions
4fabcfa3ab 📝 Update release notes 2021-01-01 20:15:01 +00:00
github-actions[bot]
5c29daadcc 👥 Update FastAPI People (#2590)
Co-authored-by: github-actions <github-actions@github.com>
2021-01-01 21:14:17 +01:00
92 changed files with 7991 additions and 409 deletions

View File

@@ -1,10 +1,10 @@
import logging
import subprocess
import sys
from collections import Counter
from collections import Counter, defaultdict
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Container, Dict, List, Optional, Set
from typing import Container, DefaultDict, Dict, List, Optional, Set
import httpx
import yaml
@@ -375,7 +375,7 @@ def get_contributors(settings: Settings):
return contributors, commentors, reviewers, authors
def get_individual_sponsors(settings: Settings, max_individual_sponsor: int = 5):
def get_individual_sponsors(settings: Settings):
nodes: List[SponsorshipAsMaintainerNode] = []
edges = get_graphql_sponsor_edges(settings=settings)
@@ -385,12 +385,12 @@ def get_individual_sponsors(settings: Settings, max_individual_sponsor: int = 5)
last_edge = edges[-1]
edges = get_graphql_sponsor_edges(settings=settings, after=last_edge.cursor)
entities: Dict[str, SponsorEntity] = {}
tiers: DefaultDict[float, Dict[str, SponsorEntity]] = defaultdict(dict)
for node in nodes:
if node.tier.monthlyPriceInDollars > max_individual_sponsor:
continue
entities[node.sponsorEntity.login] = node.sponsorEntity
return entities
tiers[node.tier.monthlyPriceInDollars][
node.sponsorEntity.login
] = node.sponsorEntity
return tiers
def get_top_users(
@@ -475,12 +475,22 @@ if __name__ == "__main__":
skip_users=skip_users,
)
sponsors_by_login = get_individual_sponsors(settings=settings)
sponsors = []
for login, sponsor in sponsors_by_login.items():
sponsors.append(
tiers = get_individual_sponsors(settings=settings)
sponsors_50 = []
for login, sponsor in tiers[50].items():
sponsors_50.append(
{"login": login, "avatarUrl": sponsor.avatarUrl, "url": sponsor.url}
)
keys = list(tiers.keys())
keys.sort(reverse=True)
sponsors = []
for key in keys:
if key >= 50:
continue
for login, sponsor in tiers[key].items():
sponsors.append(
{"login": login, "avatarUrl": sponsor.avatarUrl, "url": sponsor.url}
)
people = {
"maintainers": maintainers,
@@ -488,6 +498,7 @@ if __name__ == "__main__":
"last_month_active": last_month_active,
"top_contributors": top_contributors,
"top_reviewers": top_reviewers,
"sponsors_50": sponsors_50,
"sponsors": sponsors,
}
people_path = Path("./docs/en/data/people.yml")

View File

@@ -13,15 +13,22 @@ jobs:
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v1
uses: actions/setup-python@v2
with:
python-version: "3.7"
- uses: actions/cache@v2
id: cache
with:
path: ${{ env.pythonLocation }}
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-docs
- name: Install Flit
if: steps.cache.outputs.cache-hit != 'true'
run: python3.7 -m pip install flit
- name: Install docs extras
if: steps.cache.outputs.cache-hit != 'true'
run: python3.7 -m flit install --extras doc
- name: Install Material for MkDocs Insiders
if: github.event.pull_request.head.repo.fork == false
if: github.event.pull_request.head.repo.fork == false && steps.cache.outputs.cache-hit != 'true'
run: pip install git+https://${{ secrets.ACTIONS_TOKEN }}@github.com/squidfunk/mkdocs-material-insiders.git
- name: Build Docs
run: python3.7 ./scripts/docs.py build-all

View File

@@ -4,12 +4,25 @@ on:
schedule:
- cron: "0 14 1 * *"
workflow_dispatch:
inputs:
debug_enabled:
description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
required: false
default: false
jobs:
fastapi-people:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
# Allow debugging with tmate
- name: Setup tmate session
uses: mxschmitt/action-tmate@v3
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }}
with:
limit-access-to-actor: true
token: ${{ secrets.ACTIONS_TOKEN }}
standard_token: ${{ secrets.GITHUB_TOKEN }}
- uses: ./.github/actions/people
with:
token: ${{ secrets.ACTIONS_TOKEN }}

View File

@@ -15,12 +15,19 @@ jobs:
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v1
uses: actions/setup-python@v2
with:
python-version: "3.6"
- uses: actions/cache@v2
id: cache
with:
path: ${{ env.pythonLocation }}
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-publish
- name: Install Flit
if: steps.cache.outputs.cache-hit != 'true'
run: pip install flit
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: flit install --symlink
- name: Publish
env:

View File

@@ -16,12 +16,19 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v1
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- uses: actions/cache@v2
id: cache
with:
path: ${{ env.pythonLocation }}
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test
- name: Install Flit
if: steps.cache.outputs.cache-hit != 'true'
run: pip install flit
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: flit install --symlink
- name: Test
run: bash scripts/test.sh

View File

@@ -40,12 +40,14 @@ The key features are:
<small>* estimation based on tests on an internal development team, building production applications.</small>
## Gold Sponsors
## Sponsors
<!-- sponsors -->
<a href="https://www.deta.sh/?ref=fastapi" target="_blank" title="The launchpad for all your (team's) ideas"><img src="https://fastapi.tiangolo.com/img/sponsors/deta.svg"></a>
<a href="https://www.investsuite.com/" target="_blank" title="Wealthtech as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/investsuite.svg"></a>
<a href="https://www.investsuite.com/jobs" target="_blank" title="Wealthtech jobs with FastAPI"><img src="https://fastapi.tiangolo.com/img/sponsors/investsuite.svg"></a>
<a href="https://www.vim.so/?utm_source=FastAPI" target="_blank" title="We help you master vim with interactive exercises"><img src="https://fastapi.tiangolo.com/img/sponsors/vimso.png"></a>
<a href="https://talkpython.fm/fastapi-sponsor" target="_blank" title="FastAPI video courses on demand from people you trust"><img src="https://fastapi.tiangolo.com/img/sponsors/talkpython.png"></a>
<!-- /sponsors -->

View File

@@ -124,7 +124,7 @@ articles:
title: Introducing Dispatch
author_link: https://netflixtechblog.com/
author: Netflix
- link: https://davidefiocco.github.io/2020/06/27/streamlit-fastapi-ml-serving.html
- link: https://davidefiocco.github.io/streamlit-fastapi-ml-serving/
title: Machine learning model serving in Python using FastAPI and streamlit
author_link: https://github.com/davidefiocco
author: Davide Fiocco
@@ -148,6 +148,18 @@ articles:
title: How to monitor your FastAPI service
author_link: https://twitter.com/louis_guitton
author: Louis Guitton
- link: https://amitness.com/2020/06/fastapi-vs-flask/
title: FastAPI for Flask Users
author_link: https://twitter.com/amitness
author: Amit Chaudhary
- link: https://valonjanuzaj.medium.com/deploy-a-dockerized-fastapi-application-to-aws-cc757830ba1b
title: Deploy a dockerized FastAPI application to AWS
author_link: https://www.linkedin.com/in/valon-januzaj-b02692187/
author: Valon Januzaj
- link: https://dompatmore.com/blog/authenticate-your-fastapi-app-with-auth0
title: Authenticate Your FastAPI App with auth0
author_link: https://twitter.com/dompatmore
author: Dom Patmore
japanese:
- link: https://qiita.com/mtitg/items/47770e9a562dd150631d
title: FastAPIDB接続してCRUDするPython製APIサーバーを構築
@@ -211,6 +223,10 @@ articles:
title: Почему Вы должны попробовать FastAPI?
author_link: https://github.com/prostomarkeloff
author: prostomarkeloff
- link: https://trkohler.com/fast-api-introduction-to-framework
title: "FastAPI: знакомимся с фреймворком"
author_link: https://www.linkedin.com/in/trkohler/
author: Troy Köhler
german:
- link: https://blog.codecentric.de/2019/08/inbetriebnahme-eines-scikit-learn-modells-mit-onnx-und-fastapi/
title: Inbetriebnahme eines scikit-learn-Modells mit ONNX und FastAPI

View File

@@ -1,379 +1,675 @@
maintainers:
- login: tiangolo
answers: 998
prs: 200
avatarUrl: https://avatars1.githubusercontent.com/u/1326112?u=05f95ca7fdead36edd9c86be46b4ef6c3c71f876&v=4
answers: 1221
prs: 222
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=05f95ca7fdead36edd9c86be46b4ef6c3c71f876&v=4
url: https://github.com/tiangolo
experts:
- login: dmontagu
count: 262
avatarUrl: https://avatars2.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
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
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4
url: https://github.com/ycd
- login: Mause
count: 174
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
url: https://github.com/Mause
- login: euri10
count: 166
avatarUrl: https://avatars3.githubusercontent.com/u/1104190?u=ffd411da5d3b7ad3aa18261317f7ddc76f763c33&v=4
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
url: https://github.com/euri10
- login: phy25
count: 129
avatarUrl: https://avatars0.githubusercontent.com/u/331403?v=4
count: 130
avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4
url: https://github.com/phy25
- login: Kludex
count: 123
avatarUrl: https://avatars1.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
url: https://github.com/Kludex
- login: Mause
count: 99
avatarUrl: https://avatars2.githubusercontent.com/u/1405026?v=4
url: https://github.com/Mause
- login: ycd
count: 92
avatarUrl: https://avatars2.githubusercontent.com/u/62724709?u=496a800351ea1009678e40b26288a2a6c0dfa8bd&v=4
url: https://github.com/ycd
- login: falkben
count: 56
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
url: https://github.com/falkben
- login: ArcLightSlavik
count: 44
avatarUrl: https://avatars3.githubusercontent.com/u/31127044?u=b81d0c33b056152513fb14749a9fe00f39887a8e&v=4
count: 50
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=6e53b1a2f340d77429d435babcec107c7cc50972&v=4
url: https://github.com/ArcLightSlavik
- login: sm-Fifteen
count: 39
avatarUrl: https://avatars0.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4
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
url: https://github.com/includeamin
- login: prostomarkeloff
count: 33
avatarUrl: https://avatars3.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4
avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4
url: https://github.com/prostomarkeloff
- login: Dustyposa
count: 31
avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4
url: https://github.com/Dustyposa
- login: krishnardt
count: 30
avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4
url: https://github.com/krishnardt
- login: insomnes
count: 30
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
url: https://github.com/insomnes
- login: wshayes
count: 29
avatarUrl: https://avatars2.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
url: https://github.com/wshayes
- login: includeamin
count: 29
avatarUrl: https://avatars1.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4
url: https://github.com/includeamin
- login: dbanty
count: 25
avatarUrl: https://avatars2.githubusercontent.com/u/43723790?u=0cf33e4f40efc2ea206a1189fd63a11344eb88ed&v=4
avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=0cf33e4f40efc2ea206a1189fd63a11344eb88ed&v=4
url: https://github.com/dbanty
- login: raphaelauv
count: 24
avatarUrl: https://avatars3.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
url: https://github.com/raphaelauv
- login: SirTelemak
count: 23
avatarUrl: https://avatars1.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4
count: 24
avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4
url: https://github.com/SirTelemak
- login: acnebs
count: 22
avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=bfd127b3e6200f4d00afd714f0fc95c2512df19b&v=4
url: https://github.com/acnebs
- login: nsidnev
count: 22
avatarUrl: https://avatars0.githubusercontent.com/u/22559461?u=a9cc3238217e21dc8796a1a500f01b722adb082c&v=4
avatarUrl: https://avatars.githubusercontent.com/u/22559461?u=a9cc3238217e21dc8796a1a500f01b722adb082c&v=4
url: https://github.com/nsidnev
- login: chris-allnutt
count: 21
avatarUrl: https://avatars0.githubusercontent.com/u/565544?v=4
avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4
url: https://github.com/chris-allnutt
- login: Dustyposa
count: 21
avatarUrl: https://avatars0.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4
url: https://github.com/Dustyposa
- login: acnebs
count: 19
avatarUrl: https://avatars2.githubusercontent.com/u/9054108?u=bfd127b3e6200f4d00afd714f0fc95c2512df19b&v=4
url: https://github.com/acnebs
- login: retnikt
count: 19
avatarUrl: https://avatars1.githubusercontent.com/u/24581770?v=4
avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4
url: https://github.com/retnikt
- login: jorgerpo
count: 17
avatarUrl: https://avatars1.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4
avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4
url: https://github.com/jorgerpo
- login: Slyfoxy
- login: nkhitrov
count: 17
avatarUrl: https://avatars1.githubusercontent.com/u/28262306?u=66ee21316275ef356081c2efc4ed7a4572e690dc&v=4
url: https://github.com/Slyfoxy
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
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
url: https://github.com/waynerv
- login: haizaar
count: 13
avatarUrl: https://avatars3.githubusercontent.com/u/58201?u=4f1f9843d69433ca0d380d95146cfe119e5fdac4&v=4
avatarUrl: https://avatars.githubusercontent.com/u/58201?u=4f1f9843d69433ca0d380d95146cfe119e5fdac4&v=4
url: https://github.com/haizaar
- login: frankie567
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=72adf1cb1d29787305c99700d669561952cea0af&v=4
url: https://github.com/frankie567
- login: zamiramir
count: 11
avatarUrl: https://avatars1.githubusercontent.com/u/40475662?u=e58ef61034e8d0d6a312cc956fb09b9c3332b449&v=4
avatarUrl: https://avatars.githubusercontent.com/u/40475662?u=e58ef61034e8d0d6a312cc956fb09b9c3332b449&v=4
url: https://github.com/zamiramir
- login: juntatalor
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/8134632?v=4
url: https://github.com/juntatalor
- login: valentin994
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/42819267?u=fdeeaa9242a59b243f8603496b00994f6951d5a2&v=4
url: https://github.com/valentin994
- login: aalifadv
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/78442260?v=4
url: https://github.com/aalifadv
- login: stefanondisponibile
count: 10
avatarUrl: https://avatars1.githubusercontent.com/u/20441825?u=ee1e59446b98f8ec2363caeda4c17164d0d9cc7d&v=4
avatarUrl: https://avatars.githubusercontent.com/u/20441825?u=ee1e59446b98f8ec2363caeda4c17164d0d9cc7d&v=4
url: https://github.com/stefanondisponibile
last_month_active:
- login: Mause
count: 51
avatarUrl: https://avatars2.githubusercontent.com/u/1405026?v=4
url: https://github.com/Mause
- login: ycd
count: 22
avatarUrl: https://avatars2.githubusercontent.com/u/62724709?u=496a800351ea1009678e40b26288a2a6c0dfa8bd&v=4
url: https://github.com/ycd
- login: Kludex
count: 14
avatarUrl: https://avatars1.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
url: https://github.com/Kludex
- login: includeamin
count: 12
avatarUrl: https://avatars1.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4
url: https://github.com/includeamin
- login: ArcLightSlavik
count: 9
avatarUrl: https://avatars3.githubusercontent.com/u/31127044?u=b81d0c33b056152513fb14749a9fe00f39887a8e&v=4
url: https://github.com/ArcLightSlavik
- 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://avatars3.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
url: https://github.com/raphaelauv
- login: frankie567
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=72adf1cb1d29787305c99700d669561952cea0af&v=4
url: https://github.com/frankie567
- login: insomnes
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
url: https://github.com/insomnes
top_contributors:
- login: waynerv
count: 17
avatarUrl: https://avatars3.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
count: 25
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
url: https://github.com/waynerv
- login: tokusumi
count: 22
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
url: https://github.com/tokusumi
- login: dmontagu
count: 16
avatarUrl: https://avatars2.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
url: https://github.com/dmontagu
- login: euri10
count: 13
avatarUrl: https://avatars3.githubusercontent.com/u/1104190?u=ffd411da5d3b7ad3aa18261317f7ddc76f763c33&v=4
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
url: https://github.com/euri10
- login: tokusumi
count: 10
avatarUrl: https://avatars0.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
url: https://github.com/tokusumi
- login: mariacamilagl
count: 9
avatarUrl: https://avatars2.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4
avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4
url: https://github.com/mariacamilagl
- login: RunningIkkyu
count: 7
avatarUrl: https://avatars0.githubusercontent.com/u/31848542?u=706e1ee3f248245f2d68b976d149d06fd5a2010d&v=4
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=706e1ee3f248245f2d68b976d149d06fd5a2010d&v=4
url: https://github.com/RunningIkkyu
- login: Serrones
count: 6
avatarUrl: https://avatars3.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
url: https://github.com/Serrones
- login: hard-coders
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=f2d3d2038c55d86d7f9348f4e6c5e30191e4ee8b&v=4
url: https://github.com/hard-coders
- login: wshayes
count: 5
avatarUrl: https://avatars2.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
url: https://github.com/wshayes
- login: SwftAlpc
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4
url: https://github.com/SwftAlpc
- login: Attsun1031
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4
url: https://github.com/Attsun1031
- login: jekirl
count: 4
avatarUrl: https://avatars3.githubusercontent.com/u/2546697?v=4
avatarUrl: https://avatars.githubusercontent.com/u/2546697?v=4
url: https://github.com/jekirl
- login: komtaki
count: 4
avatarUrl: https://avatars1.githubusercontent.com/u/39375566?v=4
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=5a44657c0544111ee3c132d9bb9951c2804f7969&v=4
url: https://github.com/komtaki
top_reviewers:
- login: Kludex
count: 62
avatarUrl: https://avatars1.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
count: 75
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
url: https://github.com/Kludex
- login: tokusumi
count: 41
avatarUrl: https://avatars0.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
count: 44
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
url: https://github.com/tokusumi
- login: ycd
count: 24
avatarUrl: https://avatars2.githubusercontent.com/u/62724709?u=496a800351ea1009678e40b26288a2a6c0dfa8bd&v=4
count: 39
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4
url: https://github.com/ycd
- login: Laineyzhang55
count: 34
avatarUrl: https://avatars.githubusercontent.com/u/59285379?v=4
url: https://github.com/Laineyzhang55
- login: waynerv
count: 32
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
url: https://github.com/waynerv
- login: AdrianDeAnda
count: 26
avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=bb7f8a0d6c9de4e9d0320a9f271210206e202250&v=4
url: https://github.com/AdrianDeAnda
- login: dmontagu
count: 23
avatarUrl: https://avatars2.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
url: https://github.com/dmontagu
- login: Laineyzhang55
count: 21
avatarUrl: https://avatars0.githubusercontent.com/u/59285379?v=4
url: https://github.com/Laineyzhang55
- login: AdrianDeAnda
count: 20
avatarUrl: https://avatars0.githubusercontent.com/u/1024932?u=bb7f8a0d6c9de4e9d0320a9f271210206e202250&v=4
url: https://github.com/AdrianDeAnda
- login: komtaki
count: 19
avatarUrl: https://avatars1.githubusercontent.com/u/39375566?v=4
count: 21
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=5a44657c0544111ee3c132d9bb9951c2804f7969&v=4
url: https://github.com/komtaki
- login: waynerv
count: 18
avatarUrl: https://avatars3.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
url: https://github.com/waynerv
- login: yanever
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/21978760?v=4
url: https://github.com/yanever
- login: SwftAlpc
count: 16
avatarUrl: https://avatars1.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4
avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4
url: https://github.com/SwftAlpc
- login: pedabraham
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/16860088?u=abf922a7b920bf8fdb7867d8b43e091f1e796178&v=4
url: https://github.com/pedabraham
- login: delhi09
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/63476957?u=6c86e59b48e0394d4db230f37fc9ad4d7e2c27c7&v=4
url: https://github.com/delhi09
- login: cassiobotaro
count: 14
avatarUrl: https://avatars2.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4
url: https://github.com/cassiobotaro
- login: yanever
count: 14
avatarUrl: https://avatars2.githubusercontent.com/u/21978760?v=4
url: https://github.com/yanever
- login: RunningIkkyu
count: 11
avatarUrl: https://avatars0.githubusercontent.com/u/31848542?u=706e1ee3f248245f2d68b976d149d06fd5a2010d&v=4
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
url: https://github.com/hard-coders
- login: sh0nk
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/6478810?u=af15d724875cec682ed8088a86d36b2798f981c0&v=4
url: https://github.com/sh0nk
- login: mariacamilagl
count: 10
avatarUrl: https://avatars2.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4
avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4
url: https://github.com/mariacamilagl
- login: Attsun1031
count: 10
avatarUrl: https://avatars2.githubusercontent.com/u/1175560?v=4
avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4
url: https://github.com/Attsun1031
- login: maoyibo
count: 10
avatarUrl: https://avatars3.githubusercontent.com/u/7887703?v=4
avatarUrl: https://avatars.githubusercontent.com/u/7887703?v=4
url: https://github.com/maoyibo
- login: PandaHun
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/13096845?u=646eba44db720e37d0dbe8e98e77ab534ea78a20&v=4
url: https://github.com/PandaHun
- login: rjNemo
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
url: https://github.com/rjNemo
- login: blt232018
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/43393471?u=172b0e0391db1aa6c1706498d6dfcb003c8a4857&v=4
url: https://github.com/blt232018
- login: Serrones
count: 7
avatarUrl: https://avatars3.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
url: https://github.com/Serrones
- login: ryuckel
count: 7
avatarUrl: https://avatars1.githubusercontent.com/u/36391432?u=094eec0cfddd5013f76f31e55e56147d78b19553&v=4
avatarUrl: https://avatars.githubusercontent.com/u/36391432?u=094eec0cfddd5013f76f31e55e56147d78b19553&v=4
url: https://github.com/ryuckel
- login: ArcLightSlavik
count: 6
avatarUrl: https://avatars3.githubusercontent.com/u/31127044?u=b81d0c33b056152513fb14749a9fe00f39887a8e&v=4
url: https://github.com/ArcLightSlavik
- login: MashhadiNima
count: 5
avatarUrl: https://avatars0.githubusercontent.com/u/49960770?u=e39b11d47188744ee07b2a1c7ce1a1bdf3c80760&v=4
url: https://github.com/MashhadiNima
- login: raphaelauv
count: 5
avatarUrl: https://avatars3.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
url: https://github.com/raphaelauv
- login: jovicon
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/21287303?u=b049eac3e51a4c0473c2efe66b4d28a7d8f2b572&v=4
url: https://github.com/jovicon
- login: NastasiaSaby
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/8245071?u=b3afd005f9e4bf080c219ef61a592b3a8004b764&v=4
url: https://github.com/NastasiaSaby
- 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
url: https://github.com/juntatalor
- login: SnkSynthesis
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/63564282?u=0078826509dbecb2fdb543f4e881c9cd06157893&v=4
url: https://github.com/SnkSynthesis
- login: euri10
count: 4
avatarUrl: https://avatars3.githubusercontent.com/u/1104190?u=ffd411da5d3b7ad3aa18261317f7ddc76f763c33&v=4
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
url: https://github.com/euri10
- login: rkbeatss
count: 4
avatarUrl: https://avatars0.githubusercontent.com/u/23391143?u=56ab6bff50be950fa8cae5cf736f2ae66e319ff3&v=4
avatarUrl: https://avatars.githubusercontent.com/u/23391143?u=56ab6bff50be950fa8cae5cf736f2ae66e319ff3&v=4
url: https://github.com/rkbeatss
- login: aviramha
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/41201924?u=6883cc4fc13a7b2e60d4deddd4be06f9c5287880&v=4
url: https://github.com/aviramha
- login: Zxilly
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/31370133?v=4
url: https://github.com/Zxilly
sponsors_50:
- login: johnadjei
avatarUrl: https://avatars.githubusercontent.com/u/767860?v=4
url: https://github.com/johnadjei
- login: wdwinslow
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4
url: https://github.com/wdwinslow
sponsors:
- login: kamalgill
avatarUrl: https://avatars.githubusercontent.com/u/133923?u=0df9181d97436ce330e9acf90ab8a54b7022efe7&v=4
url: https://github.com/kamalgill
- login: grillazz
avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=16d7d0ffa5dfb99f8834f8f76d90e138ba09b94a&v=4
url: https://github.com/grillazz
- login: CarlosDomingues
avatarUrl: https://avatars.githubusercontent.com/u/11181378?u=4c15832fa030a5f3fd024ca4912093b4b59a40bd&v=4
url: https://github.com/CarlosDomingues
- 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: samuelcolvin
avatarUrl: https://avatars3.githubusercontent.com/u/4039449?u=807390ba9cfe23906c3bf8a0d56aaca3cf2bfa0d&v=4
avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=807390ba9cfe23906c3bf8a0d56aaca3cf2bfa0d&v=4
url: https://github.com/samuelcolvin
- login: mkeen
avatarUrl: https://avatars3.githubusercontent.com/u/38221?u=03e076e08a10a4de0d48a348f1aab0223c5cf24a&v=4
url: https://github.com/mkeen
- login: jokull
avatarUrl: https://avatars.githubusercontent.com/u/701?u=0532b62166893d5160ef795c4c8b7512d971af05&v=4
url: https://github.com/jokull
- login: wshayes
avatarUrl: https://avatars2.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
url: https://github.com/wshayes
- login: lukin0110
avatarUrl: https://avatars1.githubusercontent.com/u/992275?u=d20b7e18b213ae7004585b382eccb542db5ffe48&v=4
url: https://github.com/lukin0110
- login: koxudaxi
avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4
url: https://github.com/koxudaxi
- login: falkben
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
url: https://github.com/falkben
- login: Mazyod
avatarUrl: https://avatars.githubusercontent.com/u/860511?u=a76c978bdf91c2b332ab8769935fa415d0a8091b&v=4
url: https://github.com/Mazyod
- login: ltieman
avatarUrl: https://avatars1.githubusercontent.com/u/1084689?u=c9bf77f5e57f98b49694870219b9bd9d1cc862e7&v=4
avatarUrl: https://avatars.githubusercontent.com/u/1084689?u=e69b17de17cb3ca141a17daa7ccbe173ceb1eb17&v=4
url: https://github.com/ltieman
- login: mrmattwright
avatarUrl: https://avatars3.githubusercontent.com/u/1277725?v=4
avatarUrl: https://avatars.githubusercontent.com/u/1277725?v=4
url: https://github.com/mrmattwright
- login: westonsteimel
avatarUrl: https://avatars.githubusercontent.com/u/1593939?u=0f2c0e3647f916fe295d62fa70da7a4c177115e3&v=4
url: https://github.com/westonsteimel
- login: timdrijvers
avatarUrl: https://avatars1.githubusercontent.com/u/1694939?v=4
avatarUrl: https://avatars.githubusercontent.com/u/1694939?v=4
url: https://github.com/timdrijvers
- login: ddahan
avatarUrl: https://avatars0.githubusercontent.com/u/1933516?u=4068dc3c5db5d3605116c4f5df6deb9fee324c33&v=4
url: https://github.com/ddahan
- login: cbonoz
avatarUrl: https://avatars0.githubusercontent.com/u/2351087?u=fd3e8030b2cc9fbfbb54a65e9890c548a016f58b&v=4
url: https://github.com/cbonoz
- login: mrgnw
avatarUrl: https://avatars3.githubusercontent.com/u/2504532?u=7ec43837a6d0afa80f96f0788744ea6341b89f97&v=4
avatarUrl: https://avatars.githubusercontent.com/u/2504532?u=7ec43837a6d0afa80f96f0788744ea6341b89f97&v=4
url: https://github.com/mrgnw
- login: paul121
avatarUrl: https://avatars2.githubusercontent.com/u/3116995?u=6e2d8691cc345e63ee02e4eb4d7cef82b1fcbedc&v=4
url: https://github.com/paul121
- 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: andre1sk
avatarUrl: https://avatars1.githubusercontent.com/u/3148093?v=4
avatarUrl: https://avatars.githubusercontent.com/u/3148093?v=4
url: https://github.com/andre1sk
- login: igorcorrea
avatarUrl: https://avatars0.githubusercontent.com/u/3438238?u=c57605077c31a8f7b2341fc4912507f91b4a5621&v=4
url: https://github.com/igorcorrea
- login: pawamoy
avatarUrl: https://avatars2.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4
url: https://github.com/pawamoy
- login: Shark009
avatarUrl: https://avatars.githubusercontent.com/u/3163309?v=4
url: https://github.com/Shark009
- login: peterHoburg
avatarUrl: https://avatars.githubusercontent.com/u/3860655?u=f55f47eb2d6a9b495e806ac5a044e3ae01ccc1fa&v=4
url: https://github.com/peterHoburg
- login: dudil
avatarUrl: https://avatars.githubusercontent.com/u/4785835?u=58b7ea39123e0507f3b2996448a27256b16fd697&v=4
url: https://github.com/dudil
- login: p141592
avatarUrl: https://avatars2.githubusercontent.com/u/5256328?u=07bc6374282ab3d08511afebaa5d511987d034f1&v=4
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: ginomempin
avatarUrl: https://avatars3.githubusercontent.com/u/6091865?v=4
avatarUrl: https://avatars.githubusercontent.com/u/6091865?v=4
url: https://github.com/ginomempin
- login: fabboe
avatarUrl: https://avatars2.githubusercontent.com/u/7251331?u=43098dddeee6514a552ee5e98bc198ecfd18fdb7&v=4
url: https://github.com/fabboe
- login: s3ich4n
avatarUrl: https://avatars.githubusercontent.com/u/6926298?u=ba3025d698e1c986655e776ae383a3d60d9d578e&v=4
url: https://github.com/s3ich4n
- login: Rehket
avatarUrl: https://avatars.githubusercontent.com/u/7015688?u=3afb0ba200feebbc7f958950e92db34df2a3c172&v=4
url: https://github.com/Rehket
- login: christippett
avatarUrl: https://avatars.githubusercontent.com/u/7218120?u=434b9d29287d7de25772d94ddc74a9bd6d969284&v=4
url: https://github.com/christippett
- login: 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
- login: Shackelford-Arden
avatarUrl: https://avatars0.githubusercontent.com/u/7362263?v=4
avatarUrl: https://avatars.githubusercontent.com/u/7362263?v=4
url: https://github.com/Shackelford-Arden
- login: macleodmac
avatarUrl: https://avatars2.githubusercontent.com/u/8996312?u=e39c68c3e0b1d264dcba4850134a291680f46355&v=4
avatarUrl: https://avatars.githubusercontent.com/u/8996312?u=e39c68c3e0b1d264dcba4850134a291680f46355&v=4
url: https://github.com/macleodmac
- login: hard-coders
avatarUrl: https://avatars3.githubusercontent.com/u/9651103?u=f2d3d2038c55d86d7f9348f4e6c5e30191e4ee8b&v=4
url: https://github.com/hard-coders
- 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://avatars2.githubusercontent.com/u/11317418?u=6de1edefb6afd0108c0ad2816bd6efc4464a9c44&v=4
avatarUrl: https://avatars.githubusercontent.com/u/11317418?u=6de1edefb6afd0108c0ad2816bd6efc4464a9c44&v=4
url: https://github.com/otivvormes
- login: iambobmae
avatarUrl: https://avatars2.githubusercontent.com/u/12390270?u=c9a35c2ee5092a9b4135ebb1f91b7f521c467031&v=4
avatarUrl: https://avatars.githubusercontent.com/u/12390270?u=c9a35c2ee5092a9b4135ebb1f91b7f521c467031&v=4
url: https://github.com/iambobmae
- login: Cozmo25
avatarUrl: https://avatars1.githubusercontent.com/u/12619962?u=679dcd6785121e14f6254e9dd0961baf3b1fef5d&v=4
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
- login: uselessscat
avatarUrl: https://avatars.githubusercontent.com/u/15332878?u=8485a1b7383c274b28f383370ee2d5f9a6cd423b&v=4
url: https://github.com/uselessscat
- login: natenka
avatarUrl: https://avatars.githubusercontent.com/u/15850513?u=00d1083c980d0b4ce32835dc07eee7f43f34fd2f&v=4
url: https://github.com/natenka
- login: la-mar
avatarUrl: https://avatars1.githubusercontent.com/u/16618300?u=7755c0521d2bb0d704f35a51464b15c1e2e6c4da&v=4
avatarUrl: https://avatars.githubusercontent.com/u/16618300?u=7755c0521d2bb0d704f35a51464b15c1e2e6c4da&v=4
url: https://github.com/la-mar
- login: robintully
avatarUrl: https://avatars2.githubusercontent.com/u/17059673?u=862b9bb01513f5acd30df97433cb97a24dbfb772&v=4
avatarUrl: https://avatars.githubusercontent.com/u/17059673?u=862b9bb01513f5acd30df97433cb97a24dbfb772&v=4
url: https://github.com/robintully
- login: ShaulAb
avatarUrl: https://avatars.githubusercontent.com/u/18129076?u=2c8d48e47f2dbee15c3f89c3d17d4c356504386c&v=4
url: https://github.com/ShaulAb
- login: wedwardbeck
avatarUrl: https://avatars3.githubusercontent.com/u/19333237?u=1de4ae2bf8d59eb4c013f21d863cbe0f2010575f&v=4
avatarUrl: https://avatars.githubusercontent.com/u/19333237?u=1de4ae2bf8d59eb4c013f21d863cbe0f2010575f&v=4
url: https://github.com/wedwardbeck
- login: linusg
avatarUrl: https://avatars3.githubusercontent.com/u/19366641?u=125e390abef8fff3b3b0d370c369cba5d7fd4c67&v=4
avatarUrl: https://avatars.githubusercontent.com/u/19366641?u=125e390abef8fff3b3b0d370c369cba5d7fd4c67&v=4
url: https://github.com/linusg
- login: SebastianLuebke
avatarUrl: https://avatars3.githubusercontent.com/u/21161532?u=ba033c1bf6851b874cfa05a8a824b9f1ff434c37&v=4
url: https://github.com/SebastianLuebke
- login: RedCarpetUp
avatarUrl: https://avatars.githubusercontent.com/u/20360440?v=4
url: https://github.com/RedCarpetUp
- login: daddycocoaman
avatarUrl: https://avatars.githubusercontent.com/u/21189155?u=756f6a17c71c538b11470f70839baacab43807ef&v=4
url: https://github.com/daddycocoaman
- login: raminsj13
avatarUrl: https://avatars2.githubusercontent.com/u/24259406?u=d51f2a526312ebba150a06936ed187ca0727d329&v=4
avatarUrl: https://avatars.githubusercontent.com/u/24259406?u=d51f2a526312ebba150a06936ed187ca0727d329&v=4
url: https://github.com/raminsj13
- login: mertguvencli
avatarUrl: https://avatars3.githubusercontent.com/u/29762151?u=16a906d90df96c8cff9ea131a575c4bc171b1523&v=4
url: https://github.com/mertguvencli
- login: comoelcometa
avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=c6751efa038561b9bc5fa56d1033d5174e10cd65&v=4
url: https://github.com/comoelcometa
- login: veprimk
avatarUrl: https://avatars.githubusercontent.com/u/29689749?u=f8cb5a15a286e522e5b189bc572d5a1a90217fb2&v=4
url: https://github.com/veprimk
- login: orihomie
avatarUrl: https://avatars3.githubusercontent.com/u/29889683?u=6bc2135a52fcb3a49e69e7d50190796618185fda&v=4
avatarUrl: https://avatars.githubusercontent.com/u/29889683?u=6bc2135a52fcb3a49e69e7d50190796618185fda&v=4
url: https://github.com/orihomie
- login: dcooper01
avatarUrl: https://avatars2.githubusercontent.com/u/32238294?u=2a83c78b7f2a5f97beeede0b604bbe44cd21b46b&v=4
url: https://github.com/dcooper01
- login: d3vzer0
avatarUrl: https://avatars3.githubusercontent.com/u/34250156?u=c50c9df0e34f411f7e5f050a72e8d89696284eba&v=4
url: https://github.com/d3vzer0
- login: AjitZK
avatarUrl: https://avatars3.githubusercontent.com/u/40203625?u=9638bfeacfa5940358188f8205ce662bba022b53&v=4
url: https://github.com/AjitZK
- login: ilias-ant
avatarUrl: https://avatars1.githubusercontent.com/u/42189572?u=064bf3a60fcb3c445ab038386321098920b3f4e4&v=4
url: https://github.com/ilias-ant
- 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
- login: mauroalejandrojm
avatarUrl: https://avatars.githubusercontent.com/u/31569442?u=cdada990a1527926a36e95f62c30a8b48bbc49a1&v=4
url: https://github.com/mauroalejandrojm
- login: public-daniel
avatarUrl: https://avatars.githubusercontent.com/u/32238294?u=0377e38dd023395c9643d5388b4e9489a24b4d34&v=4
url: https://github.com/public-daniel
- login: ybressler
avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=6621dc9ab53b697912ab2a32211bb29ae90a9112&v=4
url: https://github.com/ybressler
- login: dbanty
avatarUrl: https://avatars2.githubusercontent.com/u/43723790?u=0cf33e4f40efc2ea206a1189fd63a11344eb88ed&v=4
avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=0cf33e4f40efc2ea206a1189fd63a11344eb88ed&v=4
url: https://github.com/dbanty
- login: dudikbender
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=494f85229115076121b3639a3806bbac1c6ae7f6&v=4
url: https://github.com/dudikbender
- login: Brontomerus
avatarUrl: https://avatars0.githubusercontent.com/u/61284158?u=c00d807195815014d0b6597b3801ee9c494802dd&v=4
avatarUrl: https://avatars.githubusercontent.com/u/61284158?u=4aee24daee1921daa722cde3fcb6701e3e37ea31&v=4
url: https://github.com/Brontomerus
- login: primer-api
avatarUrl: https://avatars2.githubusercontent.com/u/62152773?u=4549d79b0ad1d30ecfbef6c6933593e90e819c75&v=4
url: https://github.com/primer-api
- login: primer-io
avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4
url: https://github.com/primer-io
- login: tkrestiankova
avatarUrl: https://avatars2.githubusercontent.com/u/67013045?u=6f06d28dba7e46aa363af2840d7b028e4d7bcbd9&v=4
avatarUrl: https://avatars.githubusercontent.com/u/67013045?v=4
url: https://github.com/tkrestiankova
- login: daverin
avatarUrl: https://avatars1.githubusercontent.com/u/70378377?u=6d1814195c0de7162820eaad95a25b423a3869c0&v=4
avatarUrl: https://avatars.githubusercontent.com/u/70378377?u=6d1814195c0de7162820eaad95a25b423a3869c0&v=4
url: https://github.com/daverin
- login: anthonycepeda
avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=892f700c79f9732211bd5221bf16eec32356a732&v=4
url: https://github.com/anthonycepeda
- login: 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: 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: eteq
avatarUrl: https://avatars.githubusercontent.com/u/346587?v=4
url: https://github.com/eteq
- login: dmig
avatarUrl: https://avatars.githubusercontent.com/u/388564?v=4
url: https://github.com/dmig
- login: hongqn
avatarUrl: https://avatars.githubusercontent.com/u/405587?u=470b4c04832e45141fd5264d3354845cc9fc6466&v=4
url: https://github.com/hongqn
- login: lukin0110
avatarUrl: https://avatars.githubusercontent.com/u/992275?u=d20b7e18b213ae7004585b382eccb542db5ffe48&v=4
url: https://github.com/lukin0110
- login: okken
avatarUrl: https://avatars.githubusercontent.com/u/1568356?u=0a991a21bdc62e2bea9ad311652f2c45f453dc84&v=4
url: https://github.com/okken
- login: cbonoz
avatarUrl: https://avatars.githubusercontent.com/u/2351087?u=fd3e8030b2cc9fbfbb54a65e9890c548a016f58b&v=4
url: https://github.com/cbonoz
- login: Atem18
avatarUrl: https://avatars.githubusercontent.com/u/2875254?v=4
url: https://github.com/Atem18
- login: paul121
avatarUrl: https://avatars.githubusercontent.com/u/3116995?u=6e2d8691cc345e63ee02e4eb4d7cef82b1fcbedc&v=4
url: https://github.com/paul121
- login: igorcorrea
avatarUrl: https://avatars.githubusercontent.com/u/3438238?u=c57605077c31a8f7b2341fc4912507f91b4a5621&v=4
url: https://github.com/igorcorrea
- login: zsinx6
avatarUrl: https://avatars.githubusercontent.com/u/3532625?v=4
url: https://github.com/zsinx6
- login: pawamoy
avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4
url: https://github.com/pawamoy
- login: spyker77
avatarUrl: https://avatars.githubusercontent.com/u/4953435?u=568baae6469628e020fe0bab16e395b7ae10c7d3&v=4
url: https://github.com/spyker77
- login: iwpnd
avatarUrl: https://avatars.githubusercontent.com/u/6152183?u=b2286006daafff5f991557344fee20b5da59639a&v=4
url: https://github.com/iwpnd
- login: holec
avatarUrl: https://avatars.githubusercontent.com/u/6438041?u=f5af71ec85b3a9d7b8139cb5af0512b02fa9ab1e&v=4
url: https://github.com/holec
- login: BartlomiejRasztabiga
avatarUrl: https://avatars.githubusercontent.com/u/8852711?u=ed213d60f7a423df31ceb1004aa3ec60e612cb98&v=4
url: https://github.com/BartlomiejRasztabiga
- login: davanstrien
avatarUrl: https://avatars.githubusercontent.com/u/8995957?u=fb2aad2b52bb4e7b56db6d7c8ecc9ae1eac1b984&v=4
url: https://github.com/davanstrien
- login: and-semakin
avatarUrl: https://avatars.githubusercontent.com/u/9129071?u=ea77ddf7de4bc375d546bf2825ed420eaddb7666&v=4
url: https://github.com/and-semakin
- login: VivianSolide
avatarUrl: https://avatars.githubusercontent.com/u/9358572?u=ffb2e2ec522a15dcd3f0af1f9fd1df4afe418afa&v=4
url: https://github.com/VivianSolide
- login: hard-coders
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=f2d3d2038c55d86d7f9348f4e6c5e30191e4ee8b&v=4
url: https://github.com/hard-coders
- login: 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: 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: 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: 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
url: https://github.com/es3n1n
- login: ilias-ant
avatarUrl: https://avatars.githubusercontent.com/u/42189572?u=064bf3a60fcb3c445ab038386321098920b3f4e4&v=4
url: https://github.com/ilias-ant
- login: akanz1
avatarUrl: https://avatars.githubusercontent.com/u/51492342?u=2280f57134118714645e16b535c1a37adf6b369b&v=4
url: https://github.com/akanz1
- login: athemeart
avatarUrl: https://avatars.githubusercontent.com/u/61623624?v=4
url: https://github.com/athemeart

View File

@@ -2,13 +2,17 @@ gold:
- url: https://www.deta.sh/?ref=fastapi
title: The launchpad for all your (team's) ideas
img: https://fastapi.tiangolo.com/img/sponsors/deta.svg
- url: https://www.investsuite.com/
title: Wealthtech as a service
img: https://fastapi.tiangolo.com/img/sponsors/investsuite.svg
silver:
- url: https://www.investsuite.com/jobs
title: Wealthtech jobs with FastAPI
img: https://fastapi.tiangolo.com/img/sponsors/investsuite.svg
- url: https://www.vim.so/?utm_source=FastAPI
title: We help you master vim with interactive exercises
img: https://fastapi.tiangolo.com/img/sponsors/vimso.png
- url: https://talkpython.fm/fastapi-sponsor
title: FastAPI video courses on demand from people you trust
img: https://fastapi.tiangolo.com/img/sponsors/talkpython.png
bronze:
- url: https://testdriven.io/courses/tdd-fastapi/
title: Learn to build high-quality web apps with best practices
img: https://fastapi.tiangolo.com/img/sponsors/testdriven.svg
- url: https://jobs.bywetransfer.com/
title: WeTransfer - We deal in big ideas. You in?
img: https://fastapi.tiangolo.com/img/sponsors/wetransfer.svg

View File

@@ -157,7 +157,7 @@ The `security_scopes` object (of class `SecurityScopes`) also provides a `scope_
We create an `HTTPException` that we can re-use (`raise`) later at several points.
In this exception, we include the scopes required (if any) as a string separated by spaces (using `scope_str`). We put that string containing the scopes in in the `WWW-Authenticate` header (this is part of the spec).
In this exception, we include the scopes required (if any) as a string separated by spaces (using `scope_str`). We put that string containing the scopes in the `WWW-Authenticate` header (this is part of the spec).
```Python hl_lines="105 107-115"
{!../../../docs_src/security/tutorial005.py!}

View File

@@ -56,10 +56,41 @@ a.internal-link::after {
text-align: center;
}
a.announce:link, a.announce:visited {
a.announce-link:link,
a.announce-link:visited {
color: #fff;
}
a.announce:hover {
a.announce-link:hover {
color: var(--md-accent-fg-color);
}
.announce-wrapper {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
align-items: center;
}
.announce-wrapper div.item {
display: none;
}
.announce-wrapper .sponsor-badge {
display: block;
position: absolute;
top: -5px;
right: 0;
font-size: 0.5rem;
color: #999;
background-color: #666;
border-radius: 10px;
padding: 0 10px;
z-index: 10;
}
.announce-wrapper>div {
min-height: 40px;
display: flex;
align-items: center;
}

View File

@@ -130,8 +130,30 @@ They are supporting my work with **FastAPI** (and others), mainly through <a hre
{% endfor %}
{% endif %}
### Bronze Sponsors
{% if sponsors %}
{% for sponsor in sponsors.bronze -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
{% endfor %}
{% endif %}
### Individual Sponsors
{% if people %}
{% if people.sponsors_50 %}
<div class="user-list user-list-center">
{% for user in people.sponsors_50 %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a></div>
{% endfor %}
</div>
{% endif %}
{% endif %}
{% if people %}
<div class="user-list user-list-center">
{% for user in people.sponsors %}

View File

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 37 KiB

View File

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View File

@@ -42,6 +42,16 @@
x="0"
y="0" />
</clipPath>
<clipPath
id="clip0-3">
<rect
width="770"
height="222.03999"
fill="#ffffff"
id="rect14-6"
x="0"
y="0" />
</clipPath>
</defs>
<metadata
id="metadata972">
@@ -103,12 +113,12 @@
</g>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.65251px;line-height:1.25;font-family:Roboto, sans-serif;-inkscape-font-specification:'Roboto, sans-serif';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:0.116313"
x="31.727283"
y="21.847746"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333px;line-height:1.25;font-family:Roboto, sans-serif;-inkscape-font-specification:'Roboto, sans-serif';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:0.116313"
x="31.874025"
y="21.589594"
id="text959"><tspan
id="tspan957"
x="31.727282"
y="21.847746"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto, sans-serif;-inkscape-font-specification:'Roboto, sans-serif';text-align:center;text-anchor:middle;stroke-width:0.116313">Wealthtech as a service</tspan></text>
x="31.874023"
y="21.589594"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333px;font-family:Roboto, sans-serif;-inkscape-font-specification:'Roboto, sans-serif';text-align:center;text-anchor:middle;stroke-width:0.116313">Wealthtech jobs with FastAPI</tspan></text>
</svg>

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

View File

@@ -40,13 +40,16 @@ The key features are:
<small>* estimation based on tests on an internal development team, building production applications.</small>
## Gold Sponsors
## Sponsors
<!-- sponsors -->
{% if sponsors %}
{% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
{% endfor -%}
{%- for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
{% endfor %}
{% endif %}

View File

@@ -128,6 +128,35 @@ function setupTermynal() {
loadVisibleTermynals();
}
function shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
while (0 !== currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
async function showRandomAnnouncement(groupId, timeInterval) {
const announceFastAPI = document.getElementById(groupId);
if (announceFastAPI) {
let children = [].slice.call(announceFastAPI.children);
children = shuffle(children)
let index = 0
const announceRandom = () => {
children.forEach((el, i) => {el.style.display = "none"});
children[index].style.display = "block"
index = (index + 1) % children.length
}
announceRandom()
setInterval(announceRandom, timeInterval
)
}
}
async function main() {
if (div) {
data = await getData()
@@ -144,6 +173,8 @@ async function main() {
}
setupTermynal();
showRandomAnnouncement('announce-left', 5000)
showRandomAnnouncement('announce-right', 10000)
}
main()

View File

@@ -2,6 +2,106 @@
## Latest Changes
## 0.65.0
### Breaking Changes - Upgrade
* ⬆️ Upgrade Starlette to `0.14.2`, including internal `UJSONResponse` migrated from Starlette. This includes several bug fixes and features from Starlette. PR [#2335](https://github.com/tiangolo/fastapi/pull/2335) by [@hanneskuettner](https://github.com/hanneskuettner).
### Translations
* 🌐 Initialize new language Polish for translations. PR [#3170](https://github.com/tiangolo/fastapi/pull/3170) by [@neternefer](https://github.com/neternefer).
### Internal
* 👷 Add GitHub Action cache to speed up CI installs. PR [#3204](https://github.com/tiangolo/fastapi/pull/3204) by [@tiangolo](https://github.com/tiangolo).
* ⬆️ Upgrade setup-python GitHub Action to v2. PR [#3203](https://github.com/tiangolo/fastapi/pull/3203) by [@tiangolo](https://github.com/tiangolo).
* 🐛 Fix docs script to generate a new translation language with `overrides` boilerplate. PR [#3202](https://github.com/tiangolo/fastapi/pull/3202) by [@tiangolo](https://github.com/tiangolo).
* ✨ Add new Deta banner badge with new sponsorship tier 🙇. PR [#3194](https://github.com/tiangolo/fastapi/pull/3194) by [@tiangolo](https://github.com/tiangolo).
* 👥 Update FastAPI People. PR [#3189](https://github.com/tiangolo/fastapi/pull/3189) by [@github-actions[bot]](https://github.com/apps/github-actions).
* 🔊 Update FastAPI People to allow better debugging. PR [#3188](https://github.com/tiangolo/fastapi/pull/3188) by [@tiangolo](https://github.com/tiangolo).
## 0.64.0
### Features
* ✨ Add support for adding multiple `examples` in request bodies and path, query, cookie, and header params. New docs: [Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#body-with-multiple-examples). Initial PR [#1267](https://github.com/tiangolo/fastapi/pull/1267) by [@austinorr](https://github.com/austinorr).
### Fixes
* 📌 Pin SQLAlchemy range for tests, as it doesn't use SemVer. PR [#3001](https://github.com/tiangolo/fastapi/pull/3001) by [@tiangolo](https://github.com/tiangolo).
* 🎨 Add newly required type annotations for mypy. PR [#2882](https://github.com/tiangolo/fastapi/pull/2882) by [@tiangolo](https://github.com/tiangolo).
* 🎨 Remove internal "type: ignore", now unnecessary. PR [#2424](https://github.com/tiangolo/fastapi/pull/2424) by [@AsakuraMizu](https://github.com/AsakuraMizu).
### Docs
* 📝 Add link to article in Russian "FastAPI: знакомимся с фреймворком". PR [#2564](https://github.com/tiangolo/fastapi/pull/2564) by [@trkohler](https://github.com/trkohler).
* 📝 Add external link to blog post "Authenticate Your FastAPI App with Auth0". PR [#2172](https://github.com/tiangolo/fastapi/pull/2172) by [@dompatmore](https://github.com/dompatmore).
* 📝 Fix broken link to article: Machine learning model serving in Python using FastAPI and Streamlit. PR [#2557](https://github.com/tiangolo/fastapi/pull/2557) by [@davidefiocco](https://github.com/davidefiocco).
* 📝 Add FastAPI Medium Article: Deploy a dockerized FastAPI application to AWS. PR [#2515](https://github.com/tiangolo/fastapi/pull/2515) by [@vjanz](https://github.com/vjanz).
* ✏ Fix typo in Tutorial - Handling Errors. PR [#2486](https://github.com/tiangolo/fastapi/pull/2486) by [@johnthagen](https://github.com/johnthagen).
* ✏ Fix typo in Security OAuth2 scopes. PR [#2407](https://github.com/tiangolo/fastapi/pull/2407) by [@jugmac00](https://github.com/jugmac00).
* ✏ Fix typo/clarify docs for SQL (Relational) Databases. PR [#2393](https://github.com/tiangolo/fastapi/pull/2393) by [@kangni](https://github.com/kangni).
* 📝 Add external link to "FastAPI for Flask Users". PR [#2280](https://github.com/tiangolo/fastapi/pull/2280) by [@amitness](https://github.com/amitness).
### Translations
* 🌐 Fix Chinese translation of Tutorial - Query Parameters, remove obsolete content. PR [#3051](https://github.com/tiangolo/fastapi/pull/3051) by [@louis70109](https://github.com/louis70109).
* 🌐 Add French translation for Tutorial - Background Tasks. PR [#3098](https://github.com/tiangolo/fastapi/pull/3098) by [@Smlep](https://github.com/Smlep).
* 🌐 Fix Korean translation for docs/ko/docs/index.md. PR [#3159](https://github.com/tiangolo/fastapi/pull/3159) by [@SueNaEunYang](https://github.com/SueNaEunYang).
* 🌐 Add Korean translation for Tutorial - Query Parameters. PR [#2390](https://github.com/tiangolo/fastapi/pull/2390) by [@hard-coders](https://github.com/hard-coders).
* 🌐 Add French translation for FastAPI People. PR [#2232](https://github.com/tiangolo/fastapi/pull/2232) by [@JulianMaurin](https://github.com/JulianMaurin).
* 🌐 Add Korean translation for Tutorial - Path Parameters. PR [#2355](https://github.com/tiangolo/fastapi/pull/2355) by [@hard-coders](https://github.com/hard-coders).
* 🌐 Add French translation for Features. PR [#2157](https://github.com/tiangolo/fastapi/pull/2157) by [@Jefidev](https://github.com/Jefidev).
* 👥 Update FastAPI People. PR [#3031](https://github.com/tiangolo/fastapi/pull/3031) by [@github-actions[bot]](https://github.com/apps/github-actions).
* 🌐 Add Chinese translation for Tutorial - Debugging. PR [#2737](https://github.com/tiangolo/fastapi/pull/2737) by [@blt232018](https://github.com/blt232018).
* 🌐 Add Chinese translation for Tutorial - Security - OAuth2 with Password (and hashing), Bearer with JWT tokens. PR [#2642](https://github.com/tiangolo/fastapi/pull/2642) by [@waynerv](https://github.com/waynerv).
* 🌐 Add Korean translation for Tutorial - Header Parameters. PR [#2589](https://github.com/tiangolo/fastapi/pull/2589) by [@mode9](https://github.com/mode9).
* 🌐 Add Chinese translation for Tutorial - Metadata and Docs URLs. PR [#2559](https://github.com/tiangolo/fastapi/pull/2559) by [@blt232018](https://github.com/blt232018).
* 🌐 Add Korean translation for Tutorial - First Steps. PR [#2323](https://github.com/tiangolo/fastapi/pull/2323) by [@hard-coders](https://github.com/hard-coders).
* 🌐 Add Chinese translation for Tutorial - CORS (Cross-Origin Resource Sharing). PR [#2540](https://github.com/tiangolo/fastapi/pull/2540) by [@blt232018](https://github.com/blt232018).
* 🌐 Add Chinese translation for Tutorial - Middleware. PR [#2334](https://github.com/tiangolo/fastapi/pull/2334) by [@lpdswing](https://github.com/lpdswing).
* 🌐 Add Korean translation for Tutorial - Intro. PR [#2317](https://github.com/tiangolo/fastapi/pull/2317) by [@hard-coders](https://github.com/hard-coders).
* 🌐 Add Chinese translation for Tutorial - Bigger Applications - Multiple Files. PR [#2453](https://github.com/tiangolo/fastapi/pull/2453) by [@waynerv](https://github.com/waynerv).
* 🌐 Add Chinese translation for Tutorial - Security - Security Intro. PR [#2443](https://github.com/tiangolo/fastapi/pull/2443) by [@waynerv](https://github.com/waynerv).
* 🌐 Add Chinese translation for Tutorial - Header Parameters. PR [#2412](https://github.com/tiangolo/fastapi/pull/2412) by [@maoyibo](https://github.com/maoyibo).
* 🌐 Add Chinese translation for Tutorial - Extra Data Types. PR [#2410](https://github.com/tiangolo/fastapi/pull/2410) by [@maoyibo](https://github.com/maoyibo).
* 🌐 Add Japanese translation for Deployment - Docker. PR [#2312](https://github.com/tiangolo/fastapi/pull/2312) by [@tokusumi](https://github.com/tokusumi).
* 🌐 Add Japanese translation for Deployment - Versions. PR [#2310](https://github.com/tiangolo/fastapi/pull/2310) by [@tokusumi](https://github.com/tokusumi).
* 🌐 Add Chinese translation for Tutorial - Cookie Parameters. PR [#2261](https://github.com/tiangolo/fastapi/pull/2261) by [@alicrazy1947](https://github.com/alicrazy1947).
* 🌐 Add Japanese translation for Tutorial - Static files. PR [#2260](https://github.com/tiangolo/fastapi/pull/2260) by [@tokusumi](https://github.com/tokusumi).
* 🌐 Add Japanese translation for Tutorial - Testing. PR [#2259](https://github.com/tiangolo/fastapi/pull/2259) by [@tokusumi](https://github.com/tokusumi).
* 🌐 Add Japanese translation for Tutorial - Debugging. PR [#2256](https://github.com/tiangolo/fastapi/pull/2256) by [@tokusumi](https://github.com/tokusumi).
* 🌐 Add Japanese translation for Tutorial - Middleware. PR [#2255](https://github.com/tiangolo/fastapi/pull/2255) by [@tokusumi](https://github.com/tokusumi).
* 🌐 Add Japanese translation for Concurrency and async / await. PR [#2058](https://github.com/tiangolo/fastapi/pull/2058) by [@tokusumi](https://github.com/tokusumi).
* 🌐 Add Chinese translation for Tutorial - Security - Simple OAuth2 with Password and Bearer. PR [#2514](https://github.com/tiangolo/fastapi/pull/2514) by [@waynerv](https://github.com/waynerv).
* 🌐 Add Japanese translation for Deployment - Deta. PR [#2314](https://github.com/tiangolo/fastapi/pull/2314) by [@tokusumi](https://github.com/tokusumi).
* 🌐 Add Chinese translation for Tutorial - Security - Get Current User. PR [#2474](https://github.com/tiangolo/fastapi/pull/2474) by [@waynerv](https://github.com/waynerv).
* 🌐 Add Japanese translation for Deployment - Manually. PR [#2313](https://github.com/tiangolo/fastapi/pull/2313) by [@tokusumi](https://github.com/tokusumi).
* 🌐 Add Japanese translation for Deployment - Intro. PR [#2309](https://github.com/tiangolo/fastapi/pull/2309) by [@tokusumi](https://github.com/tokusumi).
* 🌐 Add Japanese translation for FastAPI People. PR [#2254](https://github.com/tiangolo/fastapi/pull/2254) by [@tokusumi](https://github.com/tokusumi).
* 🌐 Add Japanese translation for Advanced - Path Operation Advanced Configuration. PR [#2124](https://github.com/tiangolo/fastapi/pull/2124) by [@Attsun1031](https://github.com/Attsun1031).
* 🌐 Add Japanese translation for External Links. PR [#2070](https://github.com/tiangolo/fastapi/pull/2070) by [@tokusumi](https://github.com/tokusumi).
* 🌐 Add Japanese translation for Tutorial - Body - Updates. PR [#1956](https://github.com/tiangolo/fastapi/pull/1956) by [@SwftAlpc](https://github.com/SwftAlpc).
* 🌐 Add Japanese translation for Tutorial - Form Data. PR [#1943](https://github.com/tiangolo/fastapi/pull/1943) by [@SwftAlpc](https://github.com/SwftAlpc).
* 🌐 Add Japanese translation for Tutorial - Cookie Parameters. PR [#1933](https://github.com/tiangolo/fastapi/pull/1933) by [@SwftAlpc](https://github.com/SwftAlpc).
### Internal
* 🔧 Update top banner, point to newsletter. PR [#3003](https://github.com/tiangolo/fastapi/pull/3003) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Disable sponsor WeTransfer. PR [#3002](https://github.com/tiangolo/fastapi/pull/3002) by [@tiangolo](https://github.com/tiangolo).
* 👥 Update FastAPI People. PR [#2880](https://github.com/tiangolo/fastapi/pull/2880) by [@github-actions[bot]](https://github.com/apps/github-actions).
* 👥 Update FastAPI People. PR [#2739](https://github.com/tiangolo/fastapi/pull/2739) by [@github-actions[bot]](https://github.com/apps/github-actions).
* 🔧 Add new Gold Sponsor Talk Python 🎉. PR [#2673](https://github.com/tiangolo/fastapi/pull/2673) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Add new Gold Sponsor vim.so 🎉. PR [#2669](https://github.com/tiangolo/fastapi/pull/2669) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Add FastAPI user survey banner. PR [#2623](https://github.com/tiangolo/fastapi/pull/2623) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Add new Bronze Sponsor(s) 🥉🎉. PR [#2622](https://github.com/tiangolo/fastapi/pull/2622) by [@tiangolo](https://github.com/tiangolo).
* 📝 Update social links: add Discord, fix GitHub. PR [#2621](https://github.com/tiangolo/fastapi/pull/2621) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update FastAPI People GitHub Sponsors order. PR [#2620](https://github.com/tiangolo/fastapi/pull/2620) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update InvestSuite sponsor data. PR [#2608](https://github.com/tiangolo/fastapi/pull/2608) by [@tiangolo](https://github.com/tiangolo).
* 👥 Update FastAPI People. PR [#2590](https://github.com/tiangolo/fastapi/pull/2590) by [@github-actions[bot]](https://github.com/apps/github-actions).
## 0.63.0
### Features

View File

@@ -39,7 +39,7 @@ This also means that if you are inside a utility function that you are calling i
The benefit of raising an exception over `return`ing a value will be more evident in the section about Dependencies and Security.
In this example, when the client request an item by an ID that doesn't exist, raise an exception with a status code of `404`:
In this example, when the client requests an item by an ID that doesn't exist, raise an exception with a status code of `404`:
```Python hl_lines="11"
{!../../../docs_src/handling_errors/tutorial001.py!}

View File

@@ -1,58 +1,109 @@
# Schema Extra - Example
# Declare Request Example Data
You can define extra information to go in JSON Schema.
You can declare examples of the data your app can receive.
A common use case is to add an `example` that will be shown in the docs.
There are several ways you can declare extra JSON Schema information.
Here are several ways to do it.
## Pydantic `schema_extra`
You can declare an example for a Pydantic model using `Config` and `schema_extra`, as described in <a href="https://pydantic-docs.helpmanual.io/usage/schema/#schema-customization" class="external-link" target="_blank">Pydantic's docs: Schema customization</a>:
You can declare an `example` for a Pydantic model using `Config` and `schema_extra`, as described in <a href="https://pydantic-docs.helpmanual.io/usage/schema/#schema-customization" class="external-link" target="_blank">Pydantic's docs: Schema customization</a>:
```Python hl_lines="15-23"
{!../../../docs_src/schema_extra_example/tutorial001.py!}
```
That extra info will be added as-is to the output JSON Schema.
That extra info will be added as-is to the output **JSON Schema** for that model, and it will be used in the API docs.
!!! tip
You could use the same technique to extend the JSON Schema and add your own custom extra info.
For example you could use it to add metadata for a frontend user interface, etc.
## `Field` additional arguments
In `Field`, `Path`, `Query`, `Body` and others you'll see later, you can also declare extra info for the JSON Schema by passing any other arbitrary arguments to the function, for example, to add an `example`:
When using `Field()` with Pydantic models, you can also declare extra info for the **JSON Schema** by passing any other arbitrary arguments to the function.
You can use this to add `example` for each field:
```Python hl_lines="4 10-13"
{!../../../docs_src/schema_extra_example/tutorial002.py!}
```
!!! warning
Keep in mind that those extra arguments passed won't add any validation, only annotation, for documentation purposes.
Keep in mind that those extra arguments passed won't add any validation, only extra information, for documentation purposes.
## `Body` additional arguments
## `example` and `examples` in OpenAPI
The same way you can pass extra info to `Field`, you can do the same with `Path`, `Query`, `Body`, etc.
When using any of:
For example, you can pass an `example` for a body request to `Body`:
* `Path()`
* `Query()`
* `Header()`
* `Cookie()`
* `Body()`
* `Form()`
* `File()`
you can also declare a data `example` or a group of `examples` with additional information that will be added to **OpenAPI**.
### `Body` with `example`
Here we pass an `example` of the data expected in `Body()`:
```Python hl_lines="21-26"
{!../../../docs_src/schema_extra_example/tutorial003.py!}
```
## Example in the docs UI
### Example in the docs UI
With any of the methods above it would look like this in the `/docs`:
<img src="/img/tutorial/body-fields/image01.png">
### `Body` with multiple `examples`
Alternatively to the single `example`, you can pass `examples` using a `dict` with **multiple examples**, each with extra information that will be added to **OpenAPI** too.
The keys of the `dict` identify each example, and each value is another `dict`.
Each specific example `dict` in the `examples` can contain:
* `summary`: Short description for the example.
* `description`: A long description that can contain Markdown text.
* `value`: This is the actual example shown, e.g. a `dict`.
* `externalValue`: alternative to `value`, a URL pointing to the example. Although this might not be supported by as many tools as `value`.
```Python hl_lines="22-48"
{!../../../docs_src/schema_extra_example/tutorial004.py!}
```
### Examples in the docs UI
With `examples` added to `Body()` the `/docs` would look like:
<img src="/img/tutorial/body-fields/image02.png">
## Technical Details
About `example` vs `examples`...
!!! warning
These are very technical details about the standards **JSON Schema** and **OpenAPI**.
JSON Schema defines a field <a href="https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5" class="external-link" target="_blank">`examples`</a> in the most recent versions, but OpenAPI is based on an older version of JSON Schema that didn't have `examples`.
If the ideas above already work for you, that might me enough, and you probably don't need these details, feel free to skip them.
So, OpenAPI defined its own <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#fixed-fields-20" class="external-link" target="_blank">`example`</a> for the same purpose (as `example`, not `examples`), and that's what is used by the docs UI (using Swagger UI).
When you add an example inside of a Pydantic model, using `schema_extra` or `Field(example="something")` that example is added to the **JSON Schema** for that Pydantic model.
So, although `example` is not part of JSON Schema, it is part of OpenAPI, and that's what will be used by the docs UI.
And that **JSON Schema** of the Pydantic model is included in the **OpenAPI** of your API, and then it's used in the docs UI.
## Other info
**JSON Schema** doesn't really have a field `example` in the standards. Recent versions of JSON Schema define a field <a href="https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5" class="external-link" target="_blank">`examples`</a>, but OpenAPI 3.0.3 is based on an older version of JSON Schema that didn't have `examples`.
The same way, you could add your own custom extra info that would be added to the JSON Schema for each model, for example to customize a frontend user interface, etc.
So, OpenAPI 3.0.3 defined its own <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#fixed-fields-20" class="external-link" target="_blank">`example`</a> for the modified version of **JSON Schema** it uses, for the same purpose (but it's a single `example`, not `examples`), and that's what is used by the API docs UI (using Swagger UI).
So, although `example` is not part of JSON Schema, it is part of OpenAPI's custom version of JSON Schema, and that's what will be used by the docs UI.
But when you use `example` or `examples` with any of the other utilities (`Query()`, `Body()`, etc.) those examples are not added to the JSON Schema that describes that data (not even to OpenAPI's own version of JSON Schema), they are added directly to the *path operation* declaration in OpenAPI (outside the parts of OpenAPI that use JSON Schema).
For `Path()`, `Query()`, `Header()`, and `Cookie()`, the `example` or `examples` are added to the <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#parameter-object" class="external-link" target="_blank">OpenAPI definition, to the `Parameter Object` (in the specification)</a>.
And for `Body()`, `File()`, and `Form()`, the `example` or `examples` are equivalently added to the <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#mediaTypeObject" class="external-link" target="_blank">OpenAPI definition, to the `Request Body Object`, in the field `content`, on the `Media Type Object` (in the specification)</a>.
On the other hand, there's a newer version of OpenAPI: **3.1.0**, recently released. It is based on the latest JSON Schema and most of the modifications from OpenAPI's custom version of JSON Schema are removed, in exchange of the features from the recent versions of JSON Schema, so all these small differences are reduced. Nevertheless, Swagger UI currently doesn't support OpenAPI 3.1.0, so, for now, it's better to continue using the ideas above.

View File

@@ -364,7 +364,7 @@ Create utility functions to:
* Read a single user by ID and by email.
* Read multiple users.
* Read a single item.
* Read multiple items.
```Python hl_lines="1 3 6-7 10-11 14-15 27-28"
{!../../../docs_src/sql_databases/sql_app/crud.py!}

View File

@@ -44,6 +44,7 @@ nav:
- it: /it/
- ja: /ja/
- ko: /ko/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
@@ -172,7 +173,9 @@ markdown_extensions:
extra:
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/typer
link: https://github.com/tiangolo/fastapi
- icon: fontawesome/brands/discord
link: https://discord.gg/VQjSZaeJmf
- icon: fontawesome/brands/twitter
link: https://twitter.com/tiangolo
- icon: fontawesome/brands/linkedin
@@ -196,6 +199,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /pl/
name: pl
- link: /pt/
name: pt - português
- link: /ru/

View File

@@ -1,9 +1,26 @@
{% 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>
{% endblock %}
<div class="announce-wrapper">
<div id="announce-left">
<div class="item">
<a class="announce-link" href="https://fastapi.tiangolo.com/newsletter/">
<span class="twemoji">
{% include ".icons/material/email.svg" %}
</span> Subscribe to the <strong>FastAPI and friends</strong> newsletter 🎉
</a>
</div>
<div class="item">
<iframe style="display: inline-block; vertical-align: middle; border: none; margin-right: 0.5rem;" src="https://github.com/sponsors/tiangolo/button" title="Sponsor tiangolo" height="35" width="116" style="border: 0;"></iframe> <a class="announce-link" target="_blank" href="https://github.com/sponsors/tiangolo">You can now sponsor <strong>FastAPI</strong> 🍰</a>
</div>
</div>
<div id="announce-right" style="position: relative;">
<div class="item">
<a title="The launchpad for all your (team's) ideas" style="display: block; position: relative;" href="https://www.deta.sh/?ref=fastapi">
<span class="sponsor-badge">sponsor</span>
<img style="display: block;" src="/img/sponsors/deta-banner.svg" />
</a>
</div>
</div>
</div>
{% endblock %}

View File

@@ -44,6 +44,7 @@ nav:
- it: /it/
- ja: /ja/
- ko: /ko/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
@@ -76,7 +77,9 @@ markdown_extensions:
extra:
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/typer
link: https://github.com/tiangolo/fastapi
- icon: fontawesome/brands/discord
link: https://discord.gg/VQjSZaeJmf
- icon: fontawesome/brands/twitter
link: https://twitter.com/tiangolo
- icon: fontawesome/brands/linkedin
@@ -100,6 +103,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /pl/
name: pl
- link: /pt/
name: pt - português
- link: /ru/

View File

@@ -0,0 +1,135 @@
# La communauté FastAPI
FastAPI a une communauté extraordinaire qui accueille des personnes de tous horizons.
## Créateur - Mainteneur
Salut! 👋
C'est moi :
{% if people %}
<div class="user-list user-list-center">
{% for user in people.maintainers %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Réponses: {{ user.answers }}</div><div class="count">Pull Requests: {{ user.prs }}</div></div>
{% endfor %}
</div>
{% endif %}
Je suis le créateur et le responsable de **FastAPI**. Vous pouvez en lire plus à ce sujet dans [Aide FastAPI - Obtenir de l'aide - Se rapprocher de l'auteur](help-fastapi.md#connect-with-the-author){.internal-link target=_blank}.
...Mais ici, je veux vous montrer la communauté.
---
**FastAPI** reçoit beaucoup de soutien de la part de la communauté. Et je tiens à souligner leurs contributions.
Ce sont ces personnes qui :
* [Aident les autres à résoudre des problèmes (questions) dans GitHub](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank}.
* [Créent des Pull Requests](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}.
* Review les Pull Requests, [particulièrement important pour les traductions](contributing.md#translations){.internal-link target=_blank}.
Une salve d'applaudissements pour eux. 👏 🙇
## Utilisateurs les plus actifs le mois dernier
Ce sont les utilisateurs qui ont [aidé le plus les autres avec des problèmes (questions) dans GitHub](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank} au cours du dernier mois. ☕
{% if people %}
<div class="user-list user-list-center">
{% for user in people.last_month_active %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Questions répondues: {{ user.count }}</div></div>
{% endfor %}
</div>
{% endif %}
## Experts
Voici les **Experts FastAPI**. 🤓
Ce sont les utilisateurs qui ont [aidé le plus les autres avec des problèmes (questions) dans GitHub](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank} depuis *toujours*.
Ils ont prouvé qu'ils étaient des experts en aidant beaucoup d'autres personnes. ✨
{% if people %}
<div class="user-list user-list-center">
{% for user in people.experts %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Questions répondues: {{ user.count }}</div></div>
{% endfor %}
</div>
{% endif %}
## Principaux contributeurs
Ces utilisateurs sont les **Principaux contributeurs**. 👷
Ces utilisateurs ont [créé le plus grand nombre de demandes Pull Request](help-fastapi.md#create-a-pull-request){.internal-link target=_blank} qui ont été *merged*.
Ils ont contribué au code source, à la documentation, aux traductions, etc. 📦
{% if people %}
<div class="user-list user-list-center">
{% for user in people.top_contributors %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Pull Requests: {{ user.count }}</div></div>
{% endfor %}
</div>
{% endif %}
Il existe de nombreux autres contributeurs (plus d'une centaine), vous pouvez les voir tous dans la <a href="https://github.com/tiangolo/fastapi/graphs/contributors" class="external-link" target="_blank">Page des contributeurs de FastAPI GitHub</a>. 👷
## Principaux Reviewers
Ces utilisateurs sont les **Principaux Reviewers**. 🕵️
### Reviewers des traductions
Je ne parle que quelques langues (et pas très bien 😅). Ainsi, les reviewers sont ceux qui ont le [**pouvoir d'approuver les traductions**](contributing.md#translations){.internal-link target=_blank} de la documentation. Sans eux, il n'y aurait pas de documentation dans plusieurs autres langues.
---
Les **Principaux Reviewers** 🕵️ ont examiné le plus grand nombre de demandes Pull Request des autres, assurant la qualité du code, de la documentation, et surtout, des **traductions**.
{% if people %}
<div class="user-list user-list-center">
{% for user in people.top_reviewers %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Reviews: {{ user.count }}</div></div>
{% endfor %}
</div>
{% endif %}
## Sponsors
Ce sont les **Sponsors**. 😎
Ils soutiennent mon travail avec **FastAPI** (et d'autres) avec <a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub Sponsors</a>.
{% if people %}
<div class="user-list user-list-center">
{% for user in people.sponsors %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a></div>
{% endfor %}
</div>
{% endif %}
## À propos des données - détails techniques
L'intention de cette page est de souligner l'effort de la communauté pour aider les autres.
Notamment en incluant des efforts qui sont normalement moins visibles, et, dans de nombreux cas, plus difficile, comme aider d'autres personnes à résoudre des problèmes et examiner les Pull Requests de traduction.
Les données sont calculées chaque mois, vous pouvez lire le <a href="https://github.com/tiangolo/fastapi/blob/master/.github/actions/people/app/main.py" class="external-link" target="_blank">code source ici</a>.
Je me réserve également le droit de mettre à jour l'algorithme, les sections, les seuils, etc. (juste au cas où 🤷).

201
docs/fr/docs/features.md Normal file
View File

@@ -0,0 +1,201 @@
# Fonctionnalités
## Fonctionnalités de FastAPI
**FastAPI** vous offre ceci:
### Basé sur des standards ouverts
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> pour la création d'API, incluant la déclaration de <abbr title="en français: routes. Aussi connu sous le nom anglais endpoints ou routes">path</abbr> <abbr title="Aussi connu sous le nom de méthodes HTTP. À savoir POST, GET, PUT, DELETE">operations</abbr>, paramètres, corps de requêtes, sécurité, etc.
* Documentation automatique des modèles de données avec <a href="http://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (comme OpenAPI est aussi basée sur JSON Schema).
* Conçue avec ces standards après une analyse méticuleuse. Plutôt qu'en rajoutant des surcouches après coup.
* Cela permet d'utiliser de la **génération automatique de code client** dans beaucoup de langages.
### Documentation automatique
Documentation d'API interactive et interface web d'exploration. Comme le framework est basé sur OpenAPI, de nombreuses options sont disponibles. Deux d'entre-elles sont incluses par défaut.
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank"><strong>Swagger UI</strong></a>, propose une documentation interactive. Vous permet de directement tester l'API depuis votre navigateur.
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Une autre documentation d'API est fournie par <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank"><strong>ReDoc</strong></a>.
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Faite en python moderne
Tout est basé sur la déclaration de type standard de **Python 3.6** (grâce à Pydantic). Pas de nouvelles syntaxes à apprendre. Juste du Python standard et moderne.
Si vous souhaitez un rappel de 2 minutes sur l'utilisation des types en Python (même si vous ne comptez pas utiliser FastAPI), jetez un oeil au tutoriel suivant: [Python Types](python-types.md){.internal-link target=_blank}.
Vous écrivez du python standard avec des annotations de types:
```Python
from typing import List, Dict
from datetime import date
from pydantic import BaseModel
# Déclare une variable comme étant une str
# et profitez de l'aide de votre IDE dans cette fonction
def main(user_id: str):
return user_id
# Un modèle Pydantic
class User(BaseModel):
id: int
name: str
joined: date
```
Qui peuvent ensuite être utilisés comme cela:
```Python
my_user: User = User(id=3, name="John Doe", joined="2018-07-19")
second_user_data = {
"id": 4,
"name": "Mary",
"joined": "2018-11-30",
}
my_second_user: User = User(**second_user_data)
```
!!! info
`**second_user_data` signifie:
Utilise les clés et valeurs du dictionnaire `second_user_data` directement comme des arguments clé-valeur. C'est équivalent à: `User(id=4, name="Mary", joined="2018-11-30")`
### Support d'éditeurs
Tout le framework a été conçu pour être facile et intuitif d'utilisation, toutes les décisions de design ont été testées sur de nombreux éditeurs avant même de commencer le développement final afin d'assurer la meilleure expérience de développement possible.
Dans le dernier sondage effectué auprès de développeurs python il était clair que <a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" class="external-link" target="_blank">la fonctionnalité la plus utilisée est "l'autocomplètion"</a>.
Tout le framwork **FastAPI** a été conçu avec cela en tête. L'autocomplétion fonctionne partout.
Vous devrez rarement revenir à la documentation.
Voici comment votre éditeur peut vous aider:
* dans <a href="https://code.visualstudio.com/" class="external-link" target="_blank">Visual Studio Code</a>:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
* dans <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a>:
![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png)
Vous aurez des propositions de complétion que vous n'auriez jamais imaginées. Par exemple la clé `prix` dans le corps d'un document JSON (qui est peut-être imbriqué) venant d'une requête.
Plus jamais vous ne vous tromperez en tapant le nom d'une clé, vous ne ferez des aller-retour entre votre code et la documentation ou vous ne scrollerez de haut en bas afin d'enfin savoir si vous devez taper `username` ou `user_name`.
### Court
Des **valeurs par défaut** sont définies pour tout, des configurations optionnelles sont présentent partout. Tous ces paramètres peuvent être ajustés afin de faire ce que vous voulez et définir l'API dont vous avez besoin.
Mais, **tout fonctionne** par défaut.
### Validation
* Validation pour la plupart (ou tous?) les **types de données** Python incluant:
* objets JSON (`dict`).
* listes JSON (`list`) définissant des types d'éléments.
* Champs String (`str`), définition de longueur minimum ou maximale.
* Nombres (`int`, `float`) avec valeur minimale and maximale, etc.
* Validation pour des types plus exotiques, tel que:
* URL.
* Email.
* UUID.
* ...et autres.
Toutes les validations sont gérées par le bien établi et robuste **Pydantic**.
### Sécurité et authentification
La sécurité et l'authentification sont intégrées. Sans aucun compromis avec les bases de données ou les modèles de données.
Tous les protocoles de sécurités sont définis dans OpenAPI, incluant:
* HTTP Basic.
* **OAuth2** (aussi avec **JWT tokens**). Jetez un oeil au tutoriel [OAuth2 avec JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
* Clés d'API dans:
* Le header.
* Les paramètres de requêtes.
* Les cookies, etc.
Plus toutes les fonctionnalités de sécurités venant de Starlette (incluant les **cookies de sessions**).
Le tout conçu en composant réutilisable facilement intégrable à vos systèmes, data stores, base de données relationnelle ou NoSQL, etc.
### Injection de dépendances
FastAPI contient un système simple mais extrêmement puissant d'<abbr title='aussi connus sous le nom de "composants", "ressources", "services", "providers"'><strong>Injection de Dépendances</strong></abbr>.
* Même les dépendances peuvent avoir des dépendances, créant une hiérarchie ou un **"graph" de dépendances**
* Tout est **automatiquement géré** par le framework
* Toutes les dépendances peuvent éxiger des données d'une requêtes et **Augmenter les contraintes d'un path operation** et de la documentation automatique.
* **Validation automatique** même pour les paramètres de *path operation* définis dans les dépendances.
* Supporte les systèmes d'authentification d'utilisateurs complexes, les **connexions de base de données**, etc.
* **Aucun compromis** avec les bases de données, les frontends, etc. Mais une intégration facile avec n'importe lequel d'entre eux.
### "Plug-ins" illimités
Ou, en d'autres termes, pas besoin d'eux, importez le code que vous voulez et utilisez le.
Tout intégration est conçue pour être si simple à utiliser (avec des dépendances) que vous pouvez créer un "plug-in" pour votre application en deux lignes de code utilisant la même syntaxe que celle de vos *path operations*
### Testé
* 100% <abbr title="La quantité de code qui est testé automatiquement">de couverture de test</abbr>.
* 100% <abbr title="Annotation de types Python, avec cela votre éditeur et autres outils externes peuvent vous fournir un meilleur support">d'annotations de type</abbr> dans le code.
* Utilisé dans des applications mises en production.
## Fonctionnalités de Starlette
**FastAPI** est complètement compatible (et basé sur) <a href="https://www.starlette.io/" class="external-link" target="_blank"><strong>Starlette</strong></a>. Le code utilisant Starlette que vous ajouterez fonctionnera donc aussi.
En fait, `FastAPI` est un sous compposant de `Starlette`. Donc, si vous savez déjà comment utiliser Starlette, la plupart des fonctionnalités fonctionneront de la même manière.
Avec **FastAPI** vous aurez toutes les fonctionnalités de **Starlette** (FastAPI est juste Starlette sous stéroïdes):
* Des performances vraiments impressionnantes. C'est l'<a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank">un des framework Python les plus rapide, à égalité avec **NodeJS** et **GO**</a>.
* Le support des **WebSockets**.
* Le support de **GraphQL**.
* Les <abbr title="En anglais: In-process background tasks">tâches d'arrière-plan.</abbr>
* Des évènements de démarrages et d'arrêt.
* Un client de test basé sur `request`
* **CORS**, GZip, Static Files, Streaming responses.
* Le support des **Sessions et Cookies**.
* Une couverture de test à 100 %.
* 100 % de la base de code avec des annotations de type.
## Fonctionnalités de Pydantic
**FastAPI** est totalement compatible avec (et basé sur) <a href="https://pydantic-docs.helpmanual.io" class="external-link" target="_blank"><strong>Pydantic</strong></a>. Le code utilisant Pydantic que vous ajouterez fonctionnera donc aussi.
Inclus des librairies externes basées, aussi, sur Pydantic, servent d'<abbr title="Object-Relational Mapper">ORM</abbr>s, <abbr title="Object-Document Mapper">ODM</abbr>s pour les bases de données.
Cela signifie aussi que, dans la plupart des cas, vous pouvez fournir l'objet reçu d'une requête **directement à la base de données**, comme tout est validé automatiquement.
Inversément, dans la plupart des cas vous pourrez juste envoyer l'objet récupéré de la base de données **directement au client**
Avec **FastAPI** vous aurez toutes les fonctionnalités de **Pydantic** (comme FastAPI est basé sur Pydantic pour toutes les manipulations de données):
* **Pas de prise de tête**:
* Pas de nouveau langage de définition de schéma à apprendre.
* Si vous connaissez le typage en python vous savez comment utiliser Pydantic.
* Aide votre **<abbr title="Integrated Development Environment, il s'agit de votre éditeur de code">IDE</abbr>/<abbr title="Programme qui analyse le code à la recherche d'erreurs">linter</abbr>/cerveau**:
* Parce que les structures de données de pydantic consistent seulement en une instance de classe que vous définissez; l'auto-complétion, le linting, mypy et votre intuition devrait être largement suffisante pour valider vos données.
* **Rapide**:
* Dans les <a href="https://pydantic-docs.helpmanual.io/#benchmarks-tag" class="external-link" target="_blank">benchmarks</a> Pydantic est plus rapide que toutes les autres librairies testées.
* Valide les **structures complexes**:
* Utilise les modèles hiérarchique de Pydantic, le `typage` Python pour les `Lists`, `Dict`, etc.
* Et les validateurs permettent aux schémas de données complexes d'être clairement et facilement définis, validés et documentés sous forme d'un schéma JSON.
* Vous pouvez avoir des objets **JSON fortements imbriqués** tout en ayant, pour chacun, de la validation et des annotations.
* **Renouvelable**:
* Pydantic permet de définir de nouveaux types de données ou vous pouvez étendre la validation avec des méthodes sur un modèle décoré avec le<abbr title="en anglais: validator decorator"> décorateur de validation</abbr>
* 100% de couverture de test.

View File

@@ -0,0 +1,94 @@
# Tâches d'arrière-plan
Vous pouvez définir des tâches d'arrière-plan qui seront exécutées après avoir retourné une réponse.
Ceci est utile pour les opérations qui doivent avoir lieu après une requête, mais où le client n'a pas réellement besoin d'attendre que l'opération soit terminée pour recevoir une réponse.
Cela comprend, par exemple :
* Les notifications par email envoyées après l'exécution d'une action :
* Étant donné que se connecter à un serveur et envoyer un email a tendance à être «lent» (plusieurs secondes), vous pouvez retourner la réponse directement et envoyer la notification en arrière-plan.
* Traiter des données :
* Par exemple, si vous recevez un fichier qui doit passer par un traitement lent, vous pouvez retourner une réponse «Accepted» (HTTP 202) puis faire le traitement en arrière-plan.
## Utiliser `BackgroundTasks`
Pour commencer, importez `BackgroundTasks` et définissez un paramètre dans votre *fonction de chemin* avec `BackgroundTasks` comme type déclaré.
```Python hl_lines="1 13"
{!../../../docs_src/background_tasks/tutorial001.py!}
```
**FastAPI** créera l'objet de type `BackgroundTasks` pour vous et le passera comme paramètre.
## Créer une fonction de tâche
Une fonction à exécuter comme tâche d'arrière-plan est juste une fonction standard qui peut recevoir des paramètres.
Elle peut être une fonction asynchrone (`async def`) ou une fonction normale (`def`), **FastAPI** saura la gérer correctement.
Dans cet exemple, la fonction de tâche écrira dans un fichier (afin de simuler un envoi d'email).
L'opération d'écriture n'utilisant ni `async` ni `await`, on définit la fonction avec un `def` normal.
```Python hl_lines="6-9"
{!../../../docs_src/background_tasks/tutorial001.py!}
```
## Ajouter une tâche d'arrière-plan
Dans votre *fonction de chemin*, passez votre fonction de tâche à l'objet de type `BackgroundTasks` (`background_tasks` ici) grâce à la méthode `.add_task()` :
```Python hl_lines="14"
{!../../../docs_src/background_tasks/tutorial001.py!}
```
`.add_task()` reçoit comme arguments :
* Une fonction de tâche à exécuter en arrière-plan (`write_notification`).
* Les arguments positionnels à passer à la fonction de tâche dans l'ordre (`email`).
* Les arguments nommés à passer à la fonction de tâche (`message="some notification"`).
## Injection de dépendances
Utiliser `BackgroundTasks` fonctionne aussi avec le système d'injection de dépendances. Vous pouvez déclarer un paramètre de type `BackgroundTasks` à différents niveaux : dans une *fonction de chemin*, dans une dépendance, dans une sous-dépendance...
**FastAPI** sait quoi faire dans chaque cas et comment réutiliser le même objet, afin que tous les paramètres de type `BackgroundTasks` soient fusionnés et que les tâches soient exécutées en arrière-plan :
```Python hl_lines="13 15 22 25"
{!../../../docs_src/background_tasks/tutorial002.py!}
```
Dans cet exemple, les messages seront écrits dans le fichier `log.txt` après que la réponse soit envoyée.
S'il y avait une `query` (paramètre nommé `q`) dans la requête, alors elle sera écrite dans `log.txt` via une tâche d'arrière-plan.
Et ensuite une autre tâche d'arrière-plan (générée dans les paramètres de la *la fonction de chemin*) écrira un message dans `log.txt` comprenant le paramètre de chemin `email`.
## Détails techniques
La classe `BackgroundTasks` provient directement de <a href="https://www.starlette.io/background/" class="external-link" target="_blank">`starlette.background`</a>.
Elle est importée/incluse directement dans **FastAPI** pour que vous puissiez l'importer depuis `fastapi` et éviter d'importer accidentellement `BackgroundTask` (sans `s` à la fin) depuis `starlette.background`.
En utilisant seulement `BackgroundTasks` (et non `BackgroundTask`), il est possible de l'utiliser en tant que paramètre de *fonction de chemin* et de laisser **FastAPI** gérer le reste pour vous, comme en utilisant l'objet `Request` directement.
Il est tout de même possible d'utiliser `BackgroundTask` seul dans **FastAPI**, mais dans ce cas il faut créer l'objet dans le code et renvoyer une `Response` Starlette l'incluant.
Plus de détails sont disponibles dans <a href="https://www.starlette.io/background/" class="external-link" target="_blank">la documentation officielle de Starlette sur les tâches d'arrière-plan</a> (via leurs classes `BackgroundTasks`et `BackgroundTask`).
## Avertissement
Si vous avez besoin de réaliser des traitements lourds en tâche d'arrière-plan et que vous n'avez pas besoin que ces traitements aient lieu dans le même process (par exemple, pas besoin de partager la mémoire, les variables, etc.), il peut s'avérer profitable d'utiliser des outils plus importants tels que <a href="https://docs.celeryproject.org" class="external-link" target="_blank">Celery</a>.
Ces outils nécessitent généralement des configurations plus complexes ainsi qu'un gestionnaire de queue de message, comme RabbitMQ ou Redis, mais ils permettent d'exécuter des tâches d'arrière-plan dans différents process, et potentiellement, sur plusieurs serveurs.
Pour voir un exemple, allez voir les [Générateurs de projets](../project-generation.md){.internal-link target=_blank}, ils incluent tous Celery déjà configuré.
Mais si vous avez besoin d'accéder aux variables et objets de la même application **FastAPI**, ou si vous avez besoin d'effectuer de petites tâches d'arrière-plan (comme envoyer des notifications par email), vous pouvez simplement vous contenter d'utiliser `BackgroundTasks`.
## Résumé
Importez et utilisez `BackgroundTasks` grâce aux paramètres de *fonction de chemin* et les dépendances pour ajouter des tâches d'arrière-plan.

View File

@@ -44,12 +44,17 @@ nav:
- it: /it/
- ja: /ja/
- ko: /ko/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
- tr: /tr/
- uk: /uk/
- zh: /zh/
- features.md
- fastapi-people.md
- Tutoriel - Guide utilisateur:
- tutorial/background-tasks.md
markdown_extensions:
- toc:
permalink: true
@@ -69,7 +74,9 @@ markdown_extensions:
extra:
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/typer
link: https://github.com/tiangolo/fastapi
- icon: fontawesome/brands/discord
link: https://discord.gg/VQjSZaeJmf
- icon: fontawesome/brands/twitter
link: https://twitter.com/tiangolo
- icon: fontawesome/brands/linkedin
@@ -93,6 +100,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /pl/
name: pl
- link: /pt/
name: pt - português
- link: /ru/

View File

@@ -44,6 +44,7 @@ nav:
- it: /it/
- ja: /ja/
- ko: /ko/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
@@ -69,7 +70,9 @@ markdown_extensions:
extra:
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/typer
link: https://github.com/tiangolo/fastapi
- icon: fontawesome/brands/discord
link: https://discord.gg/VQjSZaeJmf
- icon: fontawesome/brands/twitter
link: https://twitter.com/tiangolo
- icon: fontawesome/brands/linkedin
@@ -93,6 +96,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /pl/
name: pl
- link: /pt/
name: pt - português
- link: /ru/

View File

@@ -0,0 +1,52 @@
# Path Operationの高度な設定
## OpenAPI operationId
!!! warning "注意"
あなたがOpenAPIの「エキスパート」でなければ、これは必要ないかもしれません。
*path operation*`operation_id` パラメータを利用することで、OpenAPIの `operationId` を設定できます。
`operation_id` は各オペレーションで一意にする必要があります。
```Python hl_lines="6"
{!../../../docs_src/path_operation_advanced_configuration/tutorial001.py!}
```
### *path operation関数* の名前をoperationIdとして使用する
APIの関数名を `operationId` として利用したい場合、すべてのAPIの関数をイテレーションし、各 *path operation* の `operationId` を `APIRoute.name` で上書きすれば可能です。
そうする場合は、すべての *path operation* を追加した後に行う必要があります。
```Python hl_lines="2 12-21 24"
{!../../../docs_src/path_operation_advanced_configuration/tutorial002.py!}
```
!!! tip "豆知識"
`app.openapi()` を手動でコールする場合、その前に`operationId`を更新する必要があります。
!!! warning "注意"
この方法をとる場合、各 *path operation関数* が一意な名前である必要があります。
それらが異なるモジュール (Pythonファイル) にあるとしてもです。
## OpenAPIから除外する
生成されるOpenAPIスキーマ (つまり、自動ドキュメント生成の仕組み) から *path operation* を除外するには、 `include_in_schema` パラメータを `False` にします。
```Python hl_lines="6"
{!../../../docs_src/path_operation_advanced_configuration/tutorial003.py!}
```
## docstringによる説明の高度な設定
*path operation関数* のdocstringからOpenAPIに使用する行を制限することができます。
`\f` (「書式送り (Form Feed)」のエスケープ文字) を付与することで、**FastAPI** はOpenAPIに使用される出力をその箇所までに制限します。
ドキュメントには表示されませんが、他のツール (例えばSphinx) では残りの部分を利用できるでしょう。
```Python hl_lines="19-29"
{!../../../docs_src/path_operation_advanced_configuration/tutorial004.py!}
```

393
docs/ja/docs/async.md Normal file
View File

@@ -0,0 +1,393 @@
# 並行処理と async / await
*path operation 関数*のための `async def` に関する詳細と非同期 (asynchronous) コード、並行処理 (Concurrency)、そして、並列処理 (Parallelism) の背景について。
## 急いでいますか?
<abbr title="too long; didn't read (長すぎて読めない人のための要約という意味のスラング)"><strong>TL;DR:</strong></abbr>
次のような、`await` を使用して呼び出すべきサードパーティライブラリを使用している場合:
```Python
results = await some_library()
```
以下の様に `async def` を使用して*path operation 関数*を宣言します。
```Python hl_lines="2"
@app.get('/')
async def read_results():
results = await some_library()
return results
```
!!! note "備考"
`async def` を使用して作成された関数の内部でしか `await` は使用できません。
---
データベース、API、ファイルシステムなどと通信し、`await` の使用をサポートしていないサードパーティライブラリ (現在のほとんどのデータベースライブラリに当てはまります) を使用している場合、次の様に、単に `def` を使用して通常通り *path operation 関数* を宣言してください:
```Python hl_lines="2"
@app.get('/')
def results():
results = some_library()
return results
```
---
アプリケーションが (どういうわけか) 他の何とも通信せず、応答を待つ必要がない場合は、`async def` を使用して下さい。
---
よく分からない場合は、通常の `def` を使用して下さい。
---
**備考**: *path operation 関数*に必要なだけ `def` と `async def` を混在させ、それぞれに最適なオプションを使用して定義できます。それに応じてFastAPIは正しい処理を行います。
とにかく、上記のいずれの場合でもFastAPIは非同期で動作し、非常に高速です。
しかし、上記のステップに従うことで、パフォーマンスの最適化を行えます。
## 技術詳細
現代版のPythonは「**非同期コード**」を、「**コルーチン**」と称されるものを利用してサポートしています。これは **`async` と `await`** 構文を用います。
次のセクションで、フレーズ内のパーツを順に見ていきましょう:
* **非同期コード**
* **`async` と `await`**
* **コルーチン**
## 非同期コード
非同期コードとは、言語💬がコード内のどこかで、コンピュータ/プログラム🤖に *他の何か* がどこか別の箇所で終了するのを待つように伝える手段を持っていることを意味します。*他の何か* は「遅いファイル📝」と呼ばれているとしましょう.
したがって、コンピュータは「遅いファイル📝」が終了するまで、他の処理ができます。
コンピュータ/プログラム🤖は再び待機する機会があるときや、その時点で行っていたすべての作業が完了するたびに戻ってきます。そして、必要な処理をしながら、コンピュータ/プログラム🤖が待っていた処理のどれかが終わっているかどうか確認します。
次に、それ🤖が最初のタスク (要するに、先程の「遅いファイル📝」)を終わらせて、そのタスクの結果を使う必要がある処理を続けます。
この「他の何かを待つ」とは、通常以下の様なものを待つような (プロセッサとRAMメモリの速度に比べて) 相対的に「遅い」<abbr title="インプットとアウトプット">I/O</abbr> 操作を指します:
* ネットワーク経由でクライアントから送信されるデータ
* ネットワーク経由でクライアントが受信する、プログラムから送信されたデータ
* システムによって読み取られ、プログラムに渡されるディスク内のファイル内容
* プログラムがシステムに渡して、ディスクに書き込む内容
* リモートAPI操作
* データベース操作の完了
* データベースクエリが結果を返すこと
* など。
実行時間のほとんどが<abbr title="インプットとアウトプット">I/O</abbr> 操作の待ち時間が占めるため、このような操作を「I/O バウンド」操作と言います。
コンピュータ/プログラムがこのような遅いタスクと「同期 (タスクの結果を取得して作業を続行するために、何もせずに、タスクが完了する瞬間を正確に待つ)」する必要がないため、「非同期」と呼ばれます。
その代わりに、「非同期」システムであることにより、いったん終了すると、タスクは、コンピュータ/プログラムが既に開始した処理がすべて完了するのをほんの少し (数マイクロ秒) 待って、結果を受け取りに戻ってきます。そして、処理を継続します。
「同期」の場合 (「非同期」とは異なり)、「シーケンシャル」という用語もよく使用されます。これは、コンピュータ/プログラムがすべてのステップを (待機が伴う場合でも別のタスクに切り替えることなく) 順番に実行するためです。
### 並行処理とハンバーガー
上記の**非同期**コードのアイデアは、**「並行処理」**と呼ばれることもあります。 **「並列処理」**とは異なります。
**並行処理**と**並列処理**はどちらも「多かれ少なかれ同時に発生するさまざまなこと」に関連しています。
ただし、*並行処理*と*並列処理*の詳細はまったく異なります。
違いを確認するには、ハンバーガーに関する次の物語を想像してみてください:
### 並行ハンバーガー
ファストフード🍔を食べようと、好きな人😍とレジに並んでおり、レジ係💁があなたの前にいる人達の注文を受けつけています。
それからあなたの番になり、好きな人😍と自分のために、2つの非常に豪華なハンバーガー🍔を注文します。
料金を支払います💸。
レジ係💁はキッチンの男👨‍🍳に向かって、あなたのハンバーガー🍔を準備しなければならないと伝えるために何か言いました (彼は現在、前のお客さんの商品を準備していますが)。
レジ係💁はあなたに番号札を渡します。
待っている間、好きな人😍と一緒にテーブルを選んで座り、好きな人😍と長い間話をします (注文したハンバーガーは非常に豪華で、準備に少し時間がかかるので✨🍔✨)。
ハンバーガー🍔を待ちながら好きな人😍とテーブルに座っている間、あなたの好きな人がなんて素晴らしく、かわいくて頭がいいんだと✨😍✨惚れ惚れしながら時間を費やすことができます。
好きな人😍と話しながら待っている間、ときどき、カウンターに表示されている番号をチェックして、自分の番かどうかを確認します。
その後、ついにあなたの番になりました。カウンターに行き、ハンバーガー🍔を手に入れてテーブルに戻ります。
あなたとあなたの好きな人😍はハンバーガー🍔を食べて、楽しい時間を過ごします✨。
---
上記のストーリーで、あなたがコンピュータ/プログラム🤖だと想像してみてください。
列にいる間、あなたはアイドル状態です😴。何も「生産的」なことをせず、ただ自分の番を待っています。しかし、レジ係💁は注文を受け取るだけなので (商品の準備をしているわけではない)、列は高速です。したがって、何も問題ありません。
それから、あなたの番になったら、実に「生産的な」作業を行います🤓、メニューを確認し、欲しいものを決め、好きな人😍の欲しいものを聞き、料金を支払い💸、現金またはカードを正しく渡したか確認し、正しく清算されたことを確認し、注文が正しく通っているかなどを確認します。
しかし、ハンバーガー🍔をまだできていないので、ハンバーガーの準備ができるまで待機🕙する必要があるため、レジ係💁との作業は「一時停止⏸」になります。
しかし、カウンターから離れて、番号札を持ってテーブルに座っているときは、注意を好きな人😍に切り替えて🔀、その上で「仕事⏯🤓」を行なえます。その後、好きな人😍といちゃつくかのような、非常に「生産的な🤓」ことを再び行います。
次に、レジ係💁は、「ハンバーガーの準備ができました🍔」と言って、カウンターのディスプレイに番号を表示しますが、表示番号があなたの番号に変わっても、すぐに狂ったように飛んで行くようなことはありません。あなたは自分の番号札を持っていって、他の人も自分の番号札があるので、あなたのハンバーガー🍔を盗む人がいないことは知っています。
なので、あなたは好きな人😍が話し終えるのを待って (現在の仕事⏯ / 処理中のタスクを終了します🤓)、優しく微笑んで、ハンバーガーを貰ってくるねと言います⏸。
次に、カウンターへ、いまから完了する最初のタスク⏯へ向かい、ハンバーガー🍔を受け取り、感謝の意を表して、テーブルに持っていきます。これで、カウンターとのやり取りのステップ/タスクが完了しました⏹。これにより、「ハンバーガーを食べる🔀⏯」という新しいタスクが作成されます。しかし、前の「ハンバーガーを取得する」というタスクは終了しました⏹。
### 並列ハンバーガー
これらが「並行ハンバーガー」ではなく、「並列ハンバーガー」であるとしましょう。
あなたは好きな人😍と並列ファストフード🍔を買おうとしています。
列に並んでいますが、何人かの料理人兼、レジ係 (8人としましょう) 👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳があなたの前にいる人達の注文を受けつけています。
8人のレジ係がそれぞれ自分で注文を受けるや否や、次の注文を受ける前にハンバーガーを準備するので、あなたの前の人達はカウンターを離れずに、ハンバーガー🍔ができるのを待っています🕙。
それからいよいよあなたの番になり、好きな人😍と自分のために、2つの非常に豪華なハンバーガー🍔を注文します。
料金を支払います💸。
レジ係はキッチンに行きます👨‍🍳。
あなたはカウンターの前に立って待ちます🕙。番号札がないので誰もあなたよりも先にハンバーガー🍔を取らないようにします。
あなたと好きな人😍は忙しいので、誰もあなたの前に来させませんし、あなたのハンバーガーが到着したとき🕙に誰にも取ることを許しません。あなたは好きな人に注意を払えません😞。
これは「同期」作業であり、レジ係/料理人👨‍🍳と「同期」します。レジ係/料理人👨‍🍳がハンバーガー🍔を完成させてあなたに渡すまで待つ🕙必要があり、ちょうどその完成の瞬間にそこにいる必要があります。そうでなければ、他の誰かに取られるかもしれません。
その後、カウンターの前で長い時間待ってから🕙、ついにレジ係/料理人👨‍🍳がハンバーガー🍔を渡しに戻ってきます。
ハンバーガー🍔を取り、好きな人😍とテーブルに行きます。
ただ食べるだけ、それでおしまいです。🍔⏹。
ほとんどの時間、カウンターの前で待つのに費やされていたので🕙、あまり話したりいちゃつくことはありませんでした😞。
---
この並列ハンバーガーのシナリオでは、あなたは2つのプロセッサを備えたコンピュータ/プログラム🤖 (あなたとあなたの好きな人😍) であり、両方とも待機🕙していて、彼らは「カウンターで待機🕙」することに専念しています⏯。
ファストフード店には8つのプロセッサ (レジ係/料理人) 👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳があります。一方、並行ハンバーガー店には2人 (レジ係と料理人) 💁👨‍🍳しかいなかったかもしれません。
しかし、それでも、最終的な体験は最高ではありません😞。
---
これは、ハンバーガー🍔の話と同等な話になります。
より「現実的な」例として、銀行を想像してみてください。
最近まで、ほとんどの銀行は複数の窓口👨‍💼👨‍💼👨‍💼👨‍💼に、行列🕙🕙🕙🕙🕙🕙🕙🕙ができていました。
すべての窓口で、次々と、一人の客とすべての作業を行います👨‍💼⏯.
その上、長時間、列に並ばなければいけません🕙。そうしないと、順番が回ってきません。
銀行🏦での用事にあなたの好きな人😍を連れて行きたくはないでしょう。
### ハンバーガーのまとめ
この「好きな人とのファストフードハンバーガー」のシナリオでは、待機🕙が多いため、並行システム⏸🔀⏯を使用する方がはるかに理にかなっています。
これは、ほとんどのWebアプリケーションに当てはまります。
多くのユーザーがいますが、サーバーは、あまり強くない回線でのリクエストの送信を待機🕙しています。
そして、レスポンスが返ってくるのをもう一度待機🕙します。
この「待機🕙」はマイクロ秒単位ですが、それでも、すべて合算すると、最終的にはかなり待機することになります。
これが、Web APIへの非同期⏸🔀⏯コードの利用が理にかなっている理由です。
ほとんどの既存の人気のあるPythonフレームワーク (FlaskやDjangoを含む) は、Pythonの新しい非同期機能ができる前に作成されました。したがって、それらをデプロイする方法は、並列実行と、新機能ほど強力ではない古い形式の非同期実行をサポートします。
しかし、WebSocketのサポートを追加するために、非同期Web Python (ASGI) の主な仕様はDjangoで開発されました。
そのような非同期性がNodeJSを人気にした理由です (NodeJSは並列ではありませんが)。そして、プログラミング言語としてのGoの強みでもあります。
そして、それは**FastAPI**で得られるパフォーマンスと同じレベルです。
また、並列処理と非同期処理を同時に実行できるため、テスト済みのほとんどのNodeJSフレームワークよりも高く、Goと同等のパフォーマンスが得られます。Goは、Cに近いコンパイル言語です <a href="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1" class="external-link" target="_blank">(Starletteに感謝します)</a>。
### 並行は並列よりも優れていますか?
いや!それはこの話の教訓ではありません。
並行処理は並列処理とは異なります。多くの待機を伴う**特定の**シナリオに適しています。そのため、一般に、Webアプリケーション開発では並列処理よりもはるかに優れています。しかし、すべてに対してより良いというわけではありません。
なので、バランスをとるために、次の物語を想像して下さい:
> あなたは大きくて汚れた家を掃除する必要があります。
*はい、以上です*。
---
待機🕙せず、家の中の複数の場所でたくさんの仕事をするだけです。
あなたはハンバーガーの例のように、最初はリビングルーム、次にキッチンのように順番にやっていくことができますが、何かを待機🕙しているわけではなく、ただひたすらに掃除をするだけで、順番は何にも影響しません。
順番の有無に関係なく (並行に) 同じ時間がかかり、同じ量の作業が行われることになるでしょう。
しかし、この場合、8人の元レジ係/料理人/現役清掃員👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳を手配できて、それぞれ (さらにあなたも) が家の別々の場所を掃除できれば、追加の助けを借りて、すべての作業を**並列**に行い、はるかに早く終了できるでしょう。
このシナリオでは、清掃員 (あなたを含む) のそれぞれがプロセッサとなり、それぞれの役割を果たします。
また、実行時間のほとんどは (待機ではなく) 実際の作業に費やされ、コンピュータでの作業は<abbr title="Central Processing Unit">CPU</abbr>によって行われます。これらの問題は「CPUバウンド」と言います。
---
CPUバウンド操作の一般的な例は、複雑な数学処理が必要なものです。
例えば:
* **オーディオ** や **画像処理**。
* **コンピュータビジョン**: 画像は数百万のピクセルで構成され、各ピクセルには3つの値/色があり、通常、これらのピクセルで何かを同時に計算する必要がある処理。
* **機械学習**: 通常、多くの「行列」と「ベクトル」の乗算が必要です。巨大なスプレッドシートに数字を入れて、それを同時に全部掛け合わせることを考えてみてください。
* **ディープラーニング**: これは機械学習のサブフィールドであるため、同じことが当てはまります。乗算する数字がある単一のスプレッドシートではなく、それらの膨大な集合で、多くの場合、それらのモデルを構築および/または使用するために特別なプロセッサを使用します。
### 並行処理 + 並列処理: Web + 機械学習
**FastAPI**を使用すると、Web開発で非常に一般的な並行処理 (NodeJSの主な魅力と同じもの) を利用できます。
ただし、機械学習システムのような **CPUバウンド** ワークロードに対して、並列処理とマルチプロセッシング (複数のプロセスが並列で実行される) の利点を活用することもできます。
さらに、Pythonが**データサイエンス**、機械学習、特にディープラーニングの主要言語であるという単純な事実により、FastAPIはデータサイエンス/機械学習のWeb APIおよびアプリケーション (他の多くのアプリケーションとの) に非常によく適合しています。
本番環境でこの並列処理を実現する方法については、[デプロイ](deployment/index.md){.internal-link target=_blank}に関するセクションを参照してください。
## `async` と `await`
現代的なバージョンのPythonには、非同期コードを定義する非常に直感的な方法があります。これにより、通常の「シーケンシャル」コードのように見え、適切なタイミングで「待機」します。
結果を返す前に待機する必要があり、これらの新しいPython機能をサポートする操作がある場合は、次のようにコーディングできます。
```Python
burgers = await get_burgers(2)
```
カギは `await` です。結果を `burgers`に保存する前に、`get_burgers(2)`の処理🕙の完了を待つ⏸必要があることをPythonに伝えます。これでPythonは、その間に (別のリクエストを受信するなど) 何か他のことができる🔀⏯ことを知ります。
`await` が機能するためには、非同期処理をサポートする関数内にある必要があります。これは、`async def` で関数を宣言するだけでよいです:
```Python hl_lines="1"
async def get_burgers(number: int):
# ハンバーガーを作成するために非同期処理を実行
return burgers
```
...`def` のかわりに:
```Python hl_lines="2"
# 非同期ではない
def get_sequential_burgers(number: int):
# ハンバーガーを作成するためにシーケンシャルな処理を実行
return burgers
```
`async def` を使用すると、Pythonにその関数内で `await` 式 (その関数の実行を「一時停止⏸」し、結果が戻るまで他の何かを実行🔀する) を認識しなければならないと伝えることができます。
`async def` 関数を呼び出すときは、「await」しなければなりません。したがって、これは機能しません:
```Python
# get_burgersはasync defで定義されているので動作しない
burgers = get_burgers(2)
```
---
したがって、 `await` で呼び出すことができるライブラリを使用している場合は、次のように `async def` を使用して、それを使用する*path operation 関数*を作成する必要があります:
```Python hl_lines="2-3"
@app.get('/burgers')
async def read_burgers():
burgers = await get_burgers(2)
return burgers
```
### より発展的な技術詳細
`await` は `async def` で定義された関数内でのみ使用できることがわかったかと思います。
しかし同時に、`async def` で定義された関数は「awaitされる」必要があります。なので、`async def` を持つ関数は、`async def` で定義された関数内でのみ呼び出せます。
では、このニワトリと卵の問題について、最初の `async` 関数をどのように呼び出すのでしょうか?
**FastAPI**を使用している場合、その「最初の」関数が*path operation 関数*であり、FastAPIが正しく実行する方法を知っているので、心配する必要はありません。
しかし、FastAPI以外で `async` / `await` を使用したい場合は、<a href="https://docs.python.org/3/library/asyncio-task.html#coroutine" class="external-link" target="_blank">公式Pythonドキュメントを参照して下さい</a>。
### 非同期コードの他の形式
`async` と `await` を使用するスタイルは、この言語では比較的新しいものです。
非同期コードの操作がはるかに簡単になります。
等価な (またはほとんど同一の) 構文が、最近のバージョンのJavaScript (ブラウザおよびNodeJS) にも最近組み込まれました。
しかし、その前は、非同期コードの処理はかなり複雑で難解でした。
以前のバージョンのPythonでは、スレッドや<a href="https://www.gevent.org/" class="external-link" target="_blank">Gevent</a>が利用できました。しかし、コードは理解、デバック、そして、考察がはるかに複雑です。
以前のバージョンのNodeJS / ブラウザJavaScriptでは、「コールバック」を使用していました。これは、<a href="http://callbackhell.com/" class="external-link" target="_blank">コールバック地獄</a>につながります。
## コルーチン
**コルーチン**は、`async def` 関数によって返されるものを指す非常に洒落た用語です。これは、開始できて、いつか終了する関数のようなものであるが、内部に `await` があるときは内部的に一時停止⏸されることもあるものだとPythonは認識しています。
`async` と `await` を用いた非同期コードを使用するすべての機能は、「コルーチン」を使用するものとして何度もまとめられています。Goの主要機能である「ゴルーチン」に相当します。
## まとめ
上述したフレーズを見てみましょう:
> 現代版のPythonは「**非同期コード**」を、「**コルーチン**」と称されるものを利用してサポートしています。これは **`async` と `await`** 構文を用います。
今では、この意味がより理解できるはずです。✨
(Starletteを介して) FastAPIに力を与えて、印象的なパフォーマンスを実現しているものはこれがすべてです。
## 非常に発展的な技術的詳細
!!! warning "注意"
恐らくスキップしても良いでしょう。
この部分は**FastAPI**の仕組みに関する非常に技術的な詳細です。
かなりの技術知識 (コルーチン、スレッド、ブロッキングなど) があり、FastAPIが `async def` と通常の `def` をどのように処理するか知りたい場合は、先に進んでください。
### Path operation 関数
*path operation 関数*を `async def` の代わりに通常の `def` で宣言すると、(サーバーをブロックするので) 直接呼び出す代わりに外部スレッドプール (awaitされる) で実行されます。
上記の方法と違った方法の別の非同期フレームワークから来ており、小さなパフォーマンス向上 (約100ナ秒) のために通常の `def` を使用して些細な演算のみ行う *path operation 関数* を定義するのに慣れている場合は、**FastAPI**ではまったく逆の効果になることに注意してください。このような場合、*path operation 関数* がブロッキング<abbr title="入力/出力: ディスクの読み取りまたは書き込み、ネットワーク通信。">I/O</abbr>を実行しないのであれば、`async def` の使用をお勧めします。
それでも、どちらの状況でも、**FastAPI**が過去のフレームワークよりも (またはそれに匹敵するほど) [高速になる](/#performance){.internal-link target=_blank}可能性があります。
### 依存関係
依存関係についても同様です。依存関係が `async def` ではなく標準の `def` 関数である場合、外部スレッドプールで実行されます。
### サブ依存関係
(関数定義のパラメーターとして) 相互に必要な複数の依存関係とサブ依存関係を設定できます。一部は `async def` で作成され、他の一部は通常の `def` で作成されます。それでも動作し、通常の `def`で作成されたものは、「awaitされる」代わりに (スレッドプールから) 外部スレッドで呼び出されます。
### その他のユーティリティ関数
あなたが直接呼び出すユーティリティ関数は通常の `def` または `async def` で作成でき、FastAPIは呼び出す方法に影響を与えません。
これは、FastAPIが呼び出す関数と対照的です: *path operation 関数*と依存関係。
ユーティリティ関数が `def` を使用した通常の関数である場合、スレッドプールではなく直接 (コードで記述したとおりに) 呼び出されます。関数が `async def` を使用して作成されている場合は、呼び出す際に `await` する必要があります。
---
繰り返しになりますが、これらは非常に技術的な詳細であり、検索して辿り着いた場合は役立つでしょう。
それ以外の場合は、上記のセクションのガイドラインで問題ないはずです: <a href="#in-a-hurry">急いでいますか?</a>。

View File

@@ -0,0 +1,240 @@
# Deta にデプロイ
このセクションでは、**FastAPI** アプリケーションを <a href="https://www.deta.sh/?ref=fastapi" class="external-link" target="_blank">Deta</a> の無料プランを利用して、簡単にデプロイする方法を学習します。🎁
所要時間は約**10分**です。
!!! info "備考"
<a href="https://www.deta.sh/?ref=fastapi" class="external-link" target="_blank">Deta</a> は **FastAPI** のスポンサーです。🎉
## ベーシックな **FastAPI** アプリ
* アプリのためのディレクトリ (例えば `./fastapideta/`) を作成し、その中に入ってください。
### FastAPI のコード
* 以下の `main.py` ファイルを作成してください:
```Python
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int):
return {"item_id": item_id}
```
### Requirements
では、同じディレクトリに以下の `requirements.txt` ファイルを作成してください:
```text
fastapi
```
!!! tip "豆知識"
アプリのローカルテストのために Uvicorn をインストールしたくなるかもしれませんが、Deta へのデプロイには不要です。
### ディレクトリ構造
以下の2つのファイルと1つの `./fastapideta/` ディレクトリがあるはずです:
```
.
└── main.py
└── requirements.txt
```
## Detaの無料アカウントの作成
それでは、<a href="https://www.deta.sh/?ref=fastapi" class="external-link" target="_blank">Detaの無料アカウント</a>を作成しましょう。必要なものはメールアドレスとパスワードだけです。
クレジットカードさえ必要ありません。
## CLIのインストール
アカウントを取得したら、Deta <abbr title="Command Line Interface application">CLI</abbr> をインストールしてください:
=== "Linux, macOS"
<div class="termy">
```console
$ curl -fsSL https://get.deta.dev/cli.sh | sh
```
</div>
=== "Windows PowerShell"
<div class="termy">
```console
$ iwr https://get.deta.dev/cli.ps1 -useb | iex
```
</div>
インストールしたら、インストールした CLI を有効にするために新たなターミナルを開いてください。
新たなターミナル上で、正しくインストールされたか確認します:
<div class="termy">
```console
$ deta --help
Deta command line interface for managing deta micros.
Complete documentation available at https://docs.deta.sh
Usage:
deta [flags]
deta [command]
Available Commands:
auth Change auth settings for a deta micro
...
```
</div>
!!! tip "豆知識"
CLI のインストールに問題が発生した場合は、<a href="https://docs.deta.sh/docs/micros/getting_started?ref=fastapi" class="external-link" target="_blank">Deta 公式ドキュメント</a>を参照してください。
## CLIでログイン
CLI から Deta にログインしてみましょう:
<div class="termy">
```console
$ deta login
Please, log in from the web page. Waiting..
Logged in successfully.
```
</div>
自動的にウェブブラウザが開いて、認証処理が行われます。
## Deta でデプロイ
次に、アプリケーションを Deta CLIでデプロイしましょう:
<div class="termy">
```console
$ deta new
Successfully created a new micro
// Notice the "endpoint" 🔍
{
"name": "fastapideta",
"runtime": "python3.7",
"endpoint": "https://qltnci.deta.dev",
"visor": "enabled",
"http_auth": "enabled"
}
Adding dependencies...
---> 100%
Successfully installed fastapi-0.61.1 pydantic-1.7.2 starlette-0.13.6
```
</div>
次のようなJSONメッセージが表示されます:
```JSON hl_lines="4"
{
"name": "fastapideta",
"runtime": "python3.7",
"endpoint": "https://qltnci.deta.dev",
"visor": "enabled",
"http_auth": "enabled"
}
```
!!! tip "豆知識"
あなたのデプロイでは異なる `"endpoint"` URLが表示されるでしょう。
## 確認
それでは、`endpoint` URLをブラウザで開いてみましょう。上記の例では `https://qltnci.deta.dev` ですが、あなたのURLは異なるはずです。
FastAPIアプリから返ってきたJSONレスポンスが表示されます:
```JSON
{
"Hello": "World"
}
```
そして `/docs` へ移動してください。上記の例では、`https://qltnci.deta.dev/docs` です。
次のようなドキュメントが表示されます:
<img src="/img/deployment/deta/image01.png">
## パブリックアクセスの有効化
デフォルトでは、Deta はクッキーを用いてアカウントの認証を行います。
しかし、準備が整えば、以下の様に公開できます:
<div class="termy">
```console
$ deta auth disable
Successfully disabled http auth
```
</div>
ここで、URLを共有するとAPIにアクセスできるようになります。🚀
## HTTPS
おめでとうございます!あなたの FastAPI アプリが Deta へデプロイされました!🎉 🍰
また、DetaがHTTPSを正しく処理するため、その処理を行う必要がなく、クライアントは暗号化された安全な通信が利用できます。✅ 🔒
## Visor を確認
ドキュメントUI (`https://qltnci.deta.dev/docs` のようなURLにある) は *path operation* `/items/{item_id}` へリクエストを送ることができます。
ID `5` の例を示します。
まず、<a href="https://web.deta.sh/" class="external-link" target="_blank">https://web.deta.sh</a> へアクセスします。
左側に各アプリの <abbr title="it comes from Micro(server)">「Micros」</abbr> というセクションが表示されます。
また、「Details」や「Visor」タブが表示されています。「Visor」タブへ移動してください。
そこでアプリに送られた直近のリクエストが調べられます。
また、それらを編集してリプレイできます。
<img src="/img/deployment/deta/image02.png">
## さらに詳しく知る
様々な箇所で永続的にデータを保存したくなるでしょう。そのためには <a href="https://docs.deta.sh/docs/base/py_tutorial?ref=fastapi" class="external-link" target="_blank">Deta Base</a> を使用できます。惜しみない **無料利用枠** もあります。
詳しくは <a href="https://docs.deta.sh?ref=fastapi" class="external-link" target="_blank">Deta ドキュメント</a>を参照してください。

View File

@@ -0,0 +1,179 @@
# Dockerを使用したデプロイ
このセクションでは以下の使い方の紹介とガイドへのリンクが確認できます:
* **5分**程度で、**FastAPI** のアプリケーションを、パフォーマンスを最大限に発揮するDockerイメージ (コンテナ)にする。
* (オプション) 開発者として必要な範囲でHTTPSを理解する。
* **20分**程度で、自動的なHTTPS生成とともにDockerのSwarmモード クラスタをセットアップする (月5ドルのシンプルなサーバー上で)。
* **10分**程度で、DockerのSwarmモード クラスタを使って、HTTPSなどを使用した完全な**FastAPI** アプリケーションの作成とデプロイ。
デプロイのために、<a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a> を利用できます。セキュリティ、再現性、開発のシンプルさなどに利点があります。
Dockerを使う場合、公式のDockerイメージが利用できます:
## <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>
このイメージは「自動チューニング」機構を含んでいます。犠牲を払うことなく、ただコードを加えるだけで自動的に高パフォーマンスを実現できます。
ただし、環境変数や設定ファイルを使って全ての設定の変更や更新を行えます。
!!! tip "豆知識"
全ての設定とオプションを確認するには、Dockerイメージページを開いて下さい: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>.
## `Dockerfile` の作成
* プロジェクトディレクトリへ移動。
* 以下の`Dockerfile` を作成:
```Dockerfile
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
COPY ./app /app
```
### より大きなアプリケーション
[Bigger Applications with Multiple Files](tutorial/bigger-applications.md){.internal-link target=_blank} セクションに倣う場合は、`Dockerfile` は上記の代わりに、以下の様になるかもしれません:
```Dockerfile
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
COPY ./app /app/app
```
### Raspberry Piなどのアーキテクチャ
Raspberry Pi (ARMプロセッサ搭載)やそれ以外のアーキテクチャでDockerが作動している場合、(マルチアーキテクチャである) Pythonベースイメージを使って、一から`Dockerfile`を作成し、Uvicornを単体で使用できます。
この場合、`Dockerfile` は以下の様になるかもしれません:
```Dockerfile
FROM python:3.7
RUN pip install fastapi uvicorn
EXPOSE 80
COPY ./app /app
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
```
## **FastAPI** コードの作成
* `app` ディレクトリを作成し、移動。
* 以下の`main.py` ファイルを作成:
```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}
```
* ここでは、以下の様なディレクトリ構造になっているはずです:
```
.
├── app
│ └── main.py
└── Dockerfile
```
## Dockerイメージをビルド
* プロジェクトディレクトリ (`app` ディレクトリを含んだ、`Dockerfile` のある場所) へ移動
* FastAPIイメージのビルド:
<div class="termy">
```console
$ docker build -t myimage .
---> 100%
```
</div>
## Dockerコンテナを起動
* 用意したイメージを基にしたコンテナの起動:
<div class="termy">
```console
$ docker run -d --name mycontainer -p 80:80 myimage
```
</div>
これで、Dockerコンテナ内に最適化されたFastAPIサーバが動作しています。使用しているサーバ (そしてCPUコア数) に沿った自動チューニングが行われています。
## 確認
DockerコンテナのURLで確認できるはずです。例えば: <a href="http://192.168.99.100/items/5?q=somequery" class="external-link" target="_blank">http://192.168.99.100/items/5?q=somequery</a> や <a href="http://127.0.0.1/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1/items/5?q=somequery</a> (もしくはDockerホストを使用したこれらと同等のもの)。
以下の様なものが返されます:
```JSON
{"item_id": 5, "q": "somequery"}
```
## 対話的APIドキュメント
ここで、<a href="http://192.168.99.100/docs" class="external-link" target="_blank">http://192.168.99.100/docs</a> や <a href="http://127.0.0.1/docs" class="external-link" target="_blank">http://127.0.0.1/docs</a> (もしくはDockerホストを使用したこれらと同等のもの) を開いて下さい。
自動生成された対話的APIドキュメントが確認できます (<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)
## その他のAPIドキュメント
また同様に、<a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> や <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a> (もしくはDockerホストを使用したこれらと同等のもの) を開いて下さい。
他の自動生成された対話的なAPIドキュメントが確認できます (<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)
## Traefik
<a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a>は、高性能なリバースプロキシ/ロードバランサーです。「TLSターミネーションプロキシ」ジョブを実行できます他の機能と切り離して
Let's Encryptと統合されています。そのため、証明書の取得と更新を含むHTTPSに関するすべての処理を実行できます。
また、Dockerとも統合されています。したがって、各アプリケーション構成でドメインを宣言し、それらの構成を読み取って、HTTPS証明書を生成し、構成に変更を加えることなく、アプリケーションにHTTPSを自動的に提供できます。
---
次のセクションに進み、この情報とツールを使用して、すべてを組み合わせます。
## TraefikとHTTPSを使用したDocker Swarmモードのクラスタ
HTTPSを処理する証明書の取得と更新を含むTraefikを使用して、Docker Swarmモードのクラスタを数分20分程度でセットアップできます。
Docker Swarmモードを使用することで、1台のマシンの「クラスタ」から開始でき1か月あたり5ドルのサーバーでもできます、後から必要なだけサーバーを拡張できます。
TraefikおよびHTTPS処理を備えたDocker Swarm Modeクラスターをセットアップするには、次のガイドに従います:
### <a href="https://medium.com/@tiangolo/docker-swarm-mode-and-traefik-for-a-https-cluster-20328dba6232" class="external-link" target="_blank">Docker Swarm Mode and Traefik for an HTTPS cluster</a>
### FastAPIアプリケーションのデプロイ
すべてを設定するための最も簡単な方法は、[**FastAPI** Project Generators](project-generation.md){.internal-link target=_blank}を使用することでしょう。
上述したTraefikとHTTPSを備えたDocker Swarm クラスタが統合されるように設計されています。
2分程度でプロジェクトが生成されます。
生成されたプロジェクトはデプロイの指示がありますが、それを実行するとさらに2分かかります。

View File

@@ -0,0 +1,7 @@
# デプロイ - イントロ
**FastAPI** 製のアプリケーションは比較的容易にデプロイできます。
ユースケースや使用しているツールによっていくつかの方法に分かれます。
次のセクションでより詳しくそれらの方法について説明します。

View File

@@ -0,0 +1,74 @@
# 手動デプロイ
**FastAPI** を手動でデプロイすることもできます。
以下の様なASGI対応のサーバをインストールする必要があります:
=== "Uvicorn"
* <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>, uvloopとhttptoolsを基にした高速なASGIサーバ。
<div class="termy">
```console
$ pip install uvicorn[standard]
---> 100%
```
</div>
!!! tip "豆知識"
`standard` を加えることで、Uvicornがインストールされ、いくつかの推奨される依存関係を利用するようになります。
これには、`asyncio` の高性能な完全互換品である `uvloop` が含まれ、並行処理のパフォーマンスが大幅に向上します。
=== "Hypercorn"
* <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>, HTTP/2にも対応しているASGIサーバ。
<div class="termy">
```console
$ pip install hypercorn
---> 100%
```
</div>
...または、これら以外のASGIサーバ。
そして、チュートリアルと同様な方法でアプリケーションを起動して下さい。ただし、以下の様に`--reload` オプションは使用しないで下さい:
=== "Uvicorn"
<div class="termy">
```console
$ uvicorn main:app --host 0.0.0.0 --port 80
<span style="color: green;">INFO</span>: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)
```
</div>
=== "Hypercorn"
<div class="termy">
```console
$ hypercorn main:app --bind 0.0.0.0:80
Running on 0.0.0.0:8080 over http (CTRL + C to quit)
```
</div>
停止した場合に自動的に再起動させるツールを設定したいかもしれません。
さらに、<a href="https://gunicorn.org/" class="external-link" target="_blank">Gunicorn</a>をインストールして<a href="https://www.uvicorn.org/#running-with-gunicorn" class="external-link" target="_blank">Uvicornのマネージャーとして使用したり</a>、複数のワーカーでHypercornを使用したいかもしれません。
ワーカー数などの微調整も行いたいかもしれません。
しかしこれら全てをやろうとすると、自動的にこれらを行うDockerイメージを使う方が楽かもしれません。

View File

@@ -0,0 +1,87 @@
# FastAPIのバージョンについて
**FastAPI** は既に多くのアプリケーションやシステムに本番環境で使われています。また、100%のテストカバレッジを維持しています。しかし、活発な開発が続いています。
高頻度で新機能が追加され、定期的にバグが修正され、実装は継続的に改善されています。
これが現在のバージョンがいまだに `0.x.x` な理由であり、それぞれのバージョンは破壊的な変更がなされる可能性があります。これは、<a href="https://semver.org/" class="external-link" target="_blank">セマンティック バージョニング</a>の規則に則っています。
**FastAPI** を使用すると本番用アプリケーションをすぐに作成できますが (すでに何度も経験しているかもしれませんが)、残りのコードが正しく動作するバージョンなのか確認しなければいけません。
## `fastapi` のバージョンを固定
最初にすべきことは、アプリケーションが正しく動作する **FastAPI** のバージョンを固定することです。
例えば、バージョン `0.45.0` を使っているとしましょう。
`requirements.txt` を使っているなら、以下の様にバージョンを指定できます:
```txt
fastapi==0.45.0
```
これは、厳密にバージョン `0.45.0` だけを使うことを意味します。
または、以下の様に固定することもできます:
```txt
fastapi>=0.45.0,<0.46.0
```
これは `0.45.0` 以上、`0.46.0` 未満のバージョンを使うことを意味します。例えば、バージョン `0.45.2` は使用可能です。
PoetryやPipenvなど、他のインストール管理ツールを使用している場合でも、それぞれパッケージのバージョンを指定する機能があります。
## 利用可能なバージョン
[Release Notes](../release-notes.md){.internal-link target=_blank}で利用可能なバージョンが確認できます (現在の最新版の確認などのため)。
## バージョンについて
セマンティック バージョニングの規約に従って、`1.0.0` 未満の全てのバージョンは破壊的な変更が加わる可能性があります。
FastAPIでは「パッチ」バージョンはバグ修正と非破壊的な変更に留めるという規約に従っています。
!!! tip "豆知識"
「パッチ」は最後の数字を指します。例えば、`0.2.3` ではパッチバージョンは `3` です。
従って、以下の様なバージョンの固定が望ましいです:
```txt
fastapi>=0.45.0,<0.46.0
```
破壊的な変更と新機能実装は「マイナー」バージョンで加えられます。
!!! tip "豆知識"
「マイナー」は真ん中の数字です。例えば、`0.2.3` ではマイナーバージョンは `2` です。
## FastAPIのバージョンのアップグレード
アプリケーションにテストを加えるべきです。
**FastAPI** では非常に簡単に実現できます (Starletteのおかげで)。ドキュメントを確認して下さい: [テスト](../tutorial/testing.md){.internal-link target=_blank}
テストを加えた後で、**FastAPI** のバージョンをより最新のものにアップグレードし、テストを実行することで全てのコードが正常に動作するか確認できます。
全てが動作するか、修正を行った上で全てのテストを通過した場合、使用している`fastapi` のバージョンをより最新のバージョンに固定できます。
## Starletteについて
`Starlette` のバージョンは固定すべきではありません。
**FastAPI** は、バージョン毎にStarletteのより新しいバージョンを使用します。
よって、最適なStarletteのバージョン選択を**FastAPI** に任せることができます。
## Pydanticについて
Pydanticは自身のテストだけでなく**FastAPI** のためのテストを含んでいます。なので、Pydanticの新たなバージョン ( `1.0.0` 以降) は全てFastAPIと整合性があります。
Pydanticのバージョンを、動作が保証できる`1.0.0`以降のいずれかのバージョンから`2.0.0` 未満の間に固定できます。
例えば:
```txt
pydantic>=1.2.0,<2.0.0
```

View File

@@ -0,0 +1,82 @@
# 外部リンク・記事
**FastAPI**には、絶えず成長している素晴らしいコミュニティがあります。
**FastAPI**に関連する投稿、記事、ツール、およびプロジェクトは多数あります。
それらの不完全なリストを以下に示します。
!!! tip "豆知識"
ここにまだ載っていない**FastAPI**に関連する記事、プロジェクト、ツールなどがある場合は、 <a href="https://github.com/tiangolo/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">プルリクエストして下さい</a>。
## 記事
### 英語
{% if external_links %}
{% for article in external_links.articles.english %}
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
{% endfor %}
{% endif %}
### 日本語
{% if external_links %}
{% for article in external_links.articles.japanese %}
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
{% endfor %}
{% endif %}
### ベトナム語
{% if external_links %}
{% for article in external_links.articles.vietnamese %}
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
{% endfor %}
{% endif %}
### ロシア語
{% if external_links %}
{% for article in external_links.articles.russian %}
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
{% endfor %}
{% endif %}
### ドイツ語
{% if external_links %}
{% for article in external_links.articles.german %}
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
{% endfor %}
{% endif %}
## ポッドキャスト
{% if external_links %}
{% for article in external_links.podcasts.english %}
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
{% endfor %}
{% endif %}
## トーク
{% if external_links %}
{% for article in external_links.talks.english %}
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
{% endfor %}
{% endif %}
## プロジェクト
`fastapi`トピックの最新のGitHubプロジェクト:
<div class="github-topic-projects">
</div>

View File

@@ -0,0 +1,172 @@
# FastAPI People
FastAPIには、様々なバックグラウンドの人々を歓迎する素晴らしいコミュニティがあります。
## Creator - Maintainer
こんにちは! 👋
これが私です:
{% 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** の作成者および Maintainer です。詳しくは [FastAPIを応援 - ヘルプの入手 - 開発者とつながる](help-fastapi.md#開発者とつながる){.internal-link target=_blank} に記載しています。
...ところで、ここではコミュニティを紹介したいと思います。
---
**FastAPI** は、コミュニティから多くのサポートを受けています。そこで、彼らの貢献にスポットライトを当てたいと思います。
紹介するのは次のような人々です:
* [GitHub issuesで他の人を助ける](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank}。
* [プルリクエストをする](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}。
* プルリクエストのレビューをする ([特に翻訳に重要](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 %}
## Experts
**FastAPI experts** を紹介します。🤓
彼らは、*これまでに* [GitHub issuesで最も多くの人を助けた](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank}ユーザーです。
多くの人を助けることでexpertsであると示されています。✨
{% if people %}
<div class="user-list user-list-center">
{% for user in people.experts %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Issues replied: {{ user.count }}</div></div>
{% endfor %}
</div>
{% endif %}
## Top Contributors
**Top Contributors** を紹介します。👷
彼らは、*マージされた* [最も多くのプルリクエストを作成した](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人以上) の contributors がいます。<a href="https://github.com/tiangolo/fastapi/graphs/contributors" class="external-link" target="_blank">FastAPI GitHub Contributors ページ</a>ですべての contributors を確認できます。👷
## Top Reviewers
以下のユーザーは **Top Reviewers** です。🕵️
### 翻訳のレビュー
私は少しの言語しか話せません (もしくはあまり上手ではありません😅)。したがって、reviewers は、ドキュメントの[**翻訳を承認する権限**](contributing.md#translations){.internal-link target=_blank}を持っています。それらがなければ、いくつかの言語のドキュメントはなかったでしょう。
---
**Top Reviewers** 🕵️は、他の人からのプルリクエストのほとんどをレビューし、コード、ドキュメント、特に**翻訳**の品質を保証しています。
{% if people %}
<div class="user-list user-list-center">
{% for user in people.top_reviewers %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Reviews: {{ user.count }}</div></div>
{% endfor %}
</div>
{% endif %}
## Sponsors
**Sponsors** を紹介します。😎
彼らは、<a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub Sponsors</a> を介して私の **FastAPI** などに関する活動を支援してくれています。
### Gold Sponsors
{% if sponsors %}
{% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
{% endfor %}
{% endif %}
### Silver Sponsors
{% if sponsors %}
{% for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
{% endfor %}
{% endif %}
{% if people %}
{% if people.sponsors_50 %}
### Bronze Sponsors
<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 %}
### Individual Sponsors
{% 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 %}
## データについて - 技術詳細
このページの目的は、他の人を助けるためのコミュニティの努力にスポットライトを当てるためです。
特に、他の人の issues を支援したり、翻訳のプルリクエストを確認したりするなど、通常は目立たず、多くの場合、より困難な作業を含みます。
データは毎月集計されます。<a href="https://github.com/tiangolo/fastapi/blob/master/.github/actions/people/app/main.py" class="external-link" target="_blank">ソースコードはこちら</a>で確認できます。
ここでは、スポンサーの貢献も強調しています。
アルゴリズム、セクション、閾値などは更新されるかもしれません (念のために 🤷)。

View File

@@ -0,0 +1,99 @@
# ボディ - 更新
## `PUT`による置換での更新
項目を更新するには<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT" class="external-link" target="_blank">HTTPの`PUT`</a>操作を使用することができます。
`jsonable_encoder`を用いて、入力データをJSON形式で保存できるデータに変換することができますNoSQLデータベース。例えば、`datetime``str`に変換します。
```Python hl_lines="30 31 32 33 34 35"
{!../../../docs_src/body_updates/tutorial001.py!}
```
既存のデータを置き換えるべきデータを受け取るために`PUT`は使用されます。
### 置換についての注意
つまり、`PUT`を使用して以下のボディで項目`bar`を更新したい場合は:
```Python
{
"name": "Barz",
"price": 3,
"description": None,
}
```
すでに格納されている属性`"tax": 20.2`を含まないため、入力モデルのデフォルト値は`"tax": 10.5`です。
そして、データはその「新しい」`10.5`の`tax`と共に保存されます。
## `PATCH`による部分的な更新
また、<a href="https://developer.mozilla.org/en-US/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)`のように。
これにより、`item`モデルの作成時に設定されたデータのみを持つ`dict`が生成され、デフォルト値は除外されます。
これを使うことで、デフォルト値を省略して、設定された(リクエストで送られた)データのみを含む`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!}
```
### 部分的更新のまとめ
まとめると、部分的な更新を適用するには、次のようにします:
* (オプションで)`PUT`の代わりに`PATCH`を使用します。
* 保存されているデータを取得します。
* そのデータをPydanticモデルにいれます。
* 入力モデルからデフォルト値を含まない`dict`を生成します(`exclude_unset`を使用します)。
* この方法では、モデル内のデフォルト値ですでに保存されている値を上書きするのではなく、ユーザーが実際に設定した値のみを更新することができます。
* 保存されているモデルのコピーを作成し、受け取った部分的な更新で属性を更新します(`update`パラメータを使用します)。
* コピーしたモデルをDBに保存できるものに変換します例えば、`jsonable_encoder`を使用します)。
* これはモデルの`.dict()`メソッドを再度利用することに匹敵しますが、値をJSONに変換できるデータ型、例えば`datetime`を`str`に変換します。
* データをDBに保存します。
* 更新されたモデルを返します。
```Python hl_lines="30 31 32 33 34 35 36 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,33 @@
# クッキーのパラメータ
クッキーのパラメータは、`Query``Path`のパラメータを定義するのと同じ方法で定義できます。
## `Cookie`をインポート
まず、`Cookie`をインポートします:
```Python hl_lines="3"
{!../../../docs_src/cookie_params/tutorial001.py!}
```
## `Cookie`のパラメータを宣言
次に、`Path`や`Query`と同じ構造を使ってクッキーのパラメータを宣言します。
最初の値がデフォルト値で、追加の検証パラメータや注釈パラメータをすべて渡すことができます:
```Python hl_lines="9"
{!../../../docs_src/cookie_params/tutorial001.py!}
```
!!! note "技術詳細"
`Cookie`は`Path`と`Query`の「姉妹」クラスです。また、同じ共通の`Param`クラスを継承しています。
しかし、`fastapi`から`Query`や`Path`、`Cookie`などをインポートする場合、それらは実際には特殊なクラスを返す関数であることを覚えておいてください。
!!! info "情報"
クッキーを宣言するには、`Cookie`を使う必要があります。なぜなら、そうしないとパラメータがクエリのパラメータとして解釈されてしまうからです。
## まとめ
クッキーは`Cookie`を使って宣言し、`Query`や`Path`と同じパターンを使用する。

View File

@@ -0,0 +1,112 @@
# デバッグ
Visual Studio CodeやPyCharmなどを使用して、エディター上でデバッガーと連携できます。
## `uvicorn` の実行
FastAPIアプリケーション上で、`uvicorn` を直接インポートして実行します:
```Python hl_lines="1 15"
{!../../../docs_src/debugging/tutorial001.py!}
```
### `__name__ == "__main__"` について
`__name__ == "__main__"` の主な目的は、ファイルが次のコマンドで呼び出されたときに実行されるコードを用意することです:
<div class="termy">
```console
$ python myapp.py
```
</div>
ただし、次のように、別のファイルからインポートされるときには呼び出されません:
```Python
from myapp import app
```
#### より詳しい説明
ファイルの名前が `myapp.py` だとします。
以下の様に実行する場合:
<div class="termy">
```console
$ python myapp.py
```
</div>
Pythonによって自動的に作成されたファイル内の内部変数 `__name__` は、値として文字列 `"__main__"` を持ちます。
なので、以下:
```Python
uvicorn.run(app, host="0.0.0.0", port=8000)
```
は実行されます。
---
そのモジュール (ファイル) をインポートした場合は、こうはなりません。
したがって、次のようなもう一つのファイル `importer.py` がある場合:
```Python
from myapp import app
# Some more code
```
`myapp.py` 内の自動変数には、値が `"__main __"` の変数 `__name__` はありません。
したがって、以下の行:
```Python
uvicorn.run(app, host="0.0.0.0", port=8000)
```
は実行されません。
!!! info "情報"
より詳しい情報は、<a href="https://docs.python.org/3/library/__main__.html" class="external-link" target="_blank">公式Pythonドキュメント</a>を参照してください。
## デバッガーでコードを実行
コードから直接Uvicornサーバーを実行しているため、デバッガーから直接Pythonプログラム (FastAPIアプリケーション) を呼び出せます。
---
例えば、Visual Studio Codeでは、次のことが可能です:
* 「デバッグ」パネルに移動。
* 「構成の追加...」
* 「Python」を選択。
* オプション「`Python: Current File (Integrated Terminal)`」を指定してデバッガーを実行。
すると、**FastAPI** コードでサーバーが起動され、ブレークポイントで停止したりするでしょう。
以下の様な画面になります:
<img src="/img/tutorial/debugging/image01.png">
---
Pycharmを使用する場合、次のことが可能です:
* 「実行」メニューをオープン。
* オプション「デバッグ...」を選択。
* 次にコンテキストメニューが表示される。
* デバッグするファイル (ここでは `main.py`) を選択。
すると、**FastAPI** コードでサーバーが起動され、ブレークポイントで停止したりするでしょう。
以下の様な画面になります:
<img src="/img/tutorial/debugging/image02.png">

View File

@@ -0,0 +1,61 @@
# ミドルウェア
**FastAPI** アプリケーションにミドルウェアを追加できます。
「ミドルウェア」は、すべての**リクエスト**に対して、それがあらゆる特定の*path operation*によって処理される前に機能する関数です。また、すべての**レスポンス**に対して、それを返す前に機能します。
* ミドルウェアはアプリケーションに届いたそれぞれの**リクエスト**を受け取ります。
* その後、その**リクエスト**に対して何かを実行したり、必要なコードを実行したりできます。
* 次に、アプリケーションの残りの部分に**リクエスト**を渡して (*path operation* によって) 処理させます。
* 次に、ミドルウェアはアプリケーション (の *path operation*) によって生成された**レスポンス**を受け取ります。
* その**レスポンス**に対して何かを実行したり、必要なコードを実行したりできます。
* そして、**レスポンス**を返します。
!!! note "技術詳細"
`yield` を使った依存関係をもつ場合は、終了コードはミドルウェアの *後に* 実行されます。
バックグラウンドタスク (後述) がある場合は、それらは全てのミドルウェアの *後に* 実行されます。
## ミドルウェアの作成
ミドルウェアを作成するには、関数の上部でデコレータ `@app.middleware("http")` を使用します。
ミドルウェア関数は以下を受け取ります:
* `request`
* パラメータとして `request` を受け取る関数 `call_next`
* この関数は、対応する*path operation*に `request` を渡します。
* 次に、対応する*path operation*によって生成された `response` を返します。
* その後、`response` を返す前にさらに `response` を変更することもできます。
```Python hl_lines="8-9 11 14"
{!../../../docs_src/middleware/tutorial001.py!}
```
!!! tip "豆知識"
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">'X-'プレフィックスを使用</a>してカスタムの独自ヘッダーを追加できます。
ただし、ブラウザのクライアントに表示させたいカスタムヘッダーがある場合は、<a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">StarletteのCORSドキュメント</a>に記載されているパラメータ `expose_headers` を使用して、それらをCORS設定に追加する必要があります ([CORS (オリジン間リソース共有)](cors.md){.internal-link target=_blank})
!!! note "技術詳細"
`from starlette.requests import Request` を使用することもできます。
**FastAPI**は、開発者の便利のためにこれを提供していますが、Starletteから直接きています。
### `response` の前後
*path operation* が `request` を受け取る前に、 `request` とともに実行されるコードを追加できます。
また `response` が生成された後、それを返す前にも追加できます。
例えば、リクエストの処理とレスポンスの生成にかかった秒数を含むカスタムヘッダー `X-Process-Time` を追加できます:
```Python hl_lines="10 12-13"
{!../../../docs_src/middleware/tutorial001.py!}
```
## その他のミドルウェア
他のミドルウェアの詳細については、[高度なユーザーガイド: 高度なミドルウェア](../advanced/middleware.md){.internal-link target=_blank}を参照してください。
次のセクションでは、ミドルウェアを使用して <abbr title="Cross-Origin Resource Sharing">CORS</abbr> を処理する方法について説明します。

View File

@@ -0,0 +1,58 @@
# フォームデータ
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`のパラメータの定義
`Body`や`Query`の場合と同じようにフォームパラメータを作成します:
```Python hl_lines="7"
{!../../../docs_src/request_forms/tutorial001.py!}
```
例えば、OAuth2仕様が使用できる方法の「パスワードフロー」と呼ばれるでは、フォームフィールドとして`username`と`password`を送信する必要があります。
<abbr title="仕様">仕様</abbr>では、フィールドの名前が`username`と`password`であることと、JSONではなくフォームフィールドとして送信されることを要求しています。
`Form`では`Body`(および`Query`や`Path`、`Cookie`)と同じメタデータとバリデーションを宣言することができます。
!!! info "情報"
`Form`は`Body`を直接継承するクラスです。
!!! tip "豆知識"
フォームのボディを宣言するには、明示的に`Form`を使用する必要があります。なぜなら、これを使わないと、パラメータはクエリパラメータやボディJSONパラメータとして解釈されるからです。
## 「フォームフィールド」について
HTMLフォーム`<form></form>`がサーバにデータを送信する方法は、通常、そのデータに「特別な」エンコーディングを使用していますが、これはJSONとは異なります。
**FastAPI** は、JSONの代わりにそのデータを適切な場所から読み込むようにします。
!!! note "技術詳細"
フォームからのデータは通常、`application/x-www-form-urlencoded`の「media type」を使用してエンコードされます。
しかし、フォームがファイルを含む場合は、`multipart/form-data`としてエンコードされます。ファイルの扱いについては次の章で説明します。
これらのエンコーディングやフォームフィールドの詳細については、<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr>の<code>POST</code></a>のウェブドキュメントを参照してください。
!!! warning "注意"
*path operation*で複数の`Form`パラメータを宣言することができますが、JSONとして受け取ることを期待している`Body`フィールドを宣言することはできません。なぜなら、リクエストは`application/json`の代わりに`application/x-www-form-urlencoded`を使ってボディをエンコードするからです。
これは **FastAPI**の制限ではなく、HTTPプロトコルの一部です。
## まとめ
フォームデータの入力パラメータを宣言するには、`Form`を使用する。

View File

@@ -0,0 +1,53 @@
# 静的ファイル
`StaticFiles` を使用して、ディレクトリから静的ファイルを自動的に提供できます。
## `aiofiles` をインストール
まず、`aiofiles` をインストールする必要があります:
<div class="termy">
```console
$ pip install aiofiles
---> 100%
```
</div>
## `StaticFiles` の使用
* `StaticFiles` をインポート。
* `StaticFiles()` インスタンスを生成し、特定のパスに「マウント」。
```Python hl_lines="2 6"
{!../../../docs_src/static_files/tutorial001.py!}
```
!!! note "技術詳細"
`from starlette.staticfiles import StaticFiles` も使用できます。
**FastAPI**は、開発者の利便性のために、`starlette.staticfiles` と同じ `fastapi.staticfiles` を提供します。しかし、実際にはStarletteから直接渡されています。
### 「マウント」とは
「マウント」とは、特定のパスに完全な「独立した」アプリケーションを追加することを意味します。これにより、すべてのサブパスの処理がなされます。
これは、マウントされたアプリケーションが完全に独立しているため、`APIRouter` とは異なります。メインアプリケーションのOpenAPIとドキュメントには、マウントされたアプリケーションの内容などは含まれません。
これについて詳しくは、**高度なユーザーガイド** をご覧ください。
## 詳細
最初の `"/static"` は、この「サブアプリケーション」が「マウント」されるサブパスを指します。したがって、`"/static"` から始まるパスはすべてサブアプリケーションによって処理されます。
`directory="static"` は、静的ファイルを含むディレクトリの名前を指します。
`name="static"` は、**FastAPI** が内部で使用できる名前を付けます。
これらのパラメータはすべて「`静的`」とは異なる場合があり、独自のアプリケーションのニーズと詳細に合わせて調整します。
## より詳しい情報
詳細とオプションについては、<a href="https://www.starlette.io/staticfiles/" class="external-link" target="_blank">Starletteの静的ファイルに関するドキュメント</a>を確認してください。

View File

@@ -0,0 +1,144 @@
# テスト
<a href="https://www.starlette.io/testclient/" class="external-link" target="_blank">Starlette</a> のおかげで、**FastAPI** アプリケーションのテストは簡単で楽しいものになっています。
<a href="http://docs.python-requests.org" class="external-link" target="_blank">Requests</a> がベースなので、非常に使いやすく直感的です。
これを使用すると、**FastAPI** と共に <a href="https://docs.pytest.org/" class="external-link" target="_blank">pytest</a> を直接利用できます。
## `TestClient` を使用
`TestClient` をインポートします。
`TestClient` を作成し、**FastAPI** に渡します。
`test_` から始まる名前の関数を作成します (これは `pytest` の標準的なコンベンションです)。
`requests` と同じ様に `TestClient` オブジェクトを使用します。
チェックしたい Python の標準的な式と共に、シンプルに `assert` 文を記述します。
```Python hl_lines="2 12 15-18"
{!../../../docs_src/app_testing/tutorial001.py!}
```
!!! tip "豆知識"
テスト関数は `async def` ではなく、通常の `def` であることに注意してください。
また、クライアントへの呼び出しも通常の呼び出しであり、`await` を使用しません。
これにより、煩雑にならずに、`pytest` を直接使用できます。
!!! note "技術詳細"
`from starlette.testclient import TestClient` も使用できます。
**FastAPI** は開発者の利便性のために `fastapi.testclient` と同じ `starlette.testclient` を提供します。しかし、実際にはStarletteから直接渡されています。
!!! tip "豆知識"
FastAPIアプリケーションへのリクエストの送信とは別に、テストで `async` 関数 (非同期データベース関数など) を呼び出したい場合は、高度なチュートリアルの[Async Tests](../advanced/async-tests.md){.internal-link target=_blank} を参照してください。
## テストの分離
実際のアプリケーションでは、おそらくテストを別のファイルに保存します。
また、**FastAPI** アプリケーションは、複数のファイル/モジュールなどで構成されている場合もあります。
### **FastAPI** アプリファイル
**FastAPI** アプリに `main.py` ファイルがあるとします:
```Python
{!../../../docs_src/app_testing/main.py!}
```
### テストファイル
次に、テストを含む `test_main.py` ファイルを作成し、`main` モジュール (`main.py`) から `app` をインポートします:
```Python
{!../../../docs_src/app_testing/test_main.py!}
```
## テスト: 例の拡張
次に、この例を拡張し、詳細を追加して、さまざまなパーツをテストする方法を確認しましょう。
### 拡張版 **FastAPI** アプリファイル
**FastAPI** アプリに `main_b.py` ファイルがあるとします。
そのファイルには、エラーを返す可能性のある `GET` オペレーションがあります。
また、いくつかのエラーを返す可能性のある `POST` オペレーションもあります。
これらの *path operation* には `X-Token` ヘッダーが必要です。
```Python
{!../../../docs_src/app_testing/main_b.py!}
```
### 拡張版テストファイル
次に、先程のものに拡張版のテストを加えた、`test_main_b.py` を作成します。
```Python
{!../../../docs_src/app_testing/test_main_b.py!}
```
リクエストに情報を渡せるクライアントが必要で、その方法がわからない場合はいつでも、`requests` での実現方法を検索 (Google) できます。
テストでも同じことを行います。
例えば:
* *パス* または *クエリ* パラメータを渡すには、それをURL自体に追加します。
* JSONボディを渡すには、Pythonオブジェクト (例: `dict`) を `json` パラメータに渡します。
* JSONの代わりに *フォームデータ* を送信する必要がある場合は、代わりに `data` パラメータを使用してください。
* *ヘッダー* を渡すには、`headers` パラメータに `dict` を渡します。
* *cookies* の場合、 `cookies` パラメータに `dict` です。
(`requests` または `TestClient` を使用して) バックエンドにデータを渡す方法の詳細は、<a href="http://docs.python-requests.org" class="external-link" target="_blank">Requestsのドキュメント</a>を確認してください。
!!! info "情報"
`TestClient` は、Pydanticモデルではなく、JSONに変換できるデータを受け取ることに注意してください。
テストにPydanticモデルがあり、テスト中にそのデータをアプリケーションに送信したい場合は、[JSON互換エンコーダ](encoder.md){.internal-link target=_blank} で説明されている `jsonable_encoder` が利用できます。
## 実行
後は、`pytest` をインストールするだけです:
<div class="termy">
```console
$ pip install pytest
---> 100%
```
</div>
ファイルを検知し、自動テストを実行し、結果のレポートを返します。
以下でテストを実行します:
<div class="termy">
```console
$ pytest
================ test session starts ================
platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: /home/user/code/superawesome-cli/app
plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1
collected 6 items
---> 100%
test_main.py <span style="color: green; white-space: pre;">...... [100%]</span>
<span style="color: green;">================= 1 passed in 0.03s =================</span>
```
</div>

View File

@@ -44,6 +44,7 @@ nav:
- it: /it/
- ja: /ja/
- ko: /ko/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
@@ -51,6 +52,7 @@ nav:
- uk: /uk/
- zh: /zh/
- features.md
- fastapi-people.md
- チュートリアル - ユーザーガイド:
- tutorial/index.md
- tutorial/first-steps.md
@@ -58,17 +60,33 @@ nav:
- tutorial/query-params.md
- tutorial/body.md
- tutorial/query-params-str-validations.md
- tutorial/cookie-params.md
- tutorial/header-params.md
- tutorial/request-forms.md
- tutorial/body-updates.md
- セキュリティ:
- tutorial/security/first-steps.md
- tutorial/middleware.md
- tutorial/cors.md
- tutorial/static-files.md
- tutorial/testing.md
- tutorial/debugging.md
- 高度なユーザーガイド:
- advanced/path-operation-advanced-configuration.md
- advanced/additional-status-codes.md
- advanced/response-directly.md
- advanced/custom-response.md
- async.md
- デプロイ:
- deployment/index.md
- deployment/versions.md
- deployment/deta.md
- deployment/docker.md
- deployment/manually.md
- project-generation.md
- alternatives.md
- history-design-future.md
- external-links.md
- benchmarks.md
- help-fastapi.md
- contributing.md
@@ -91,7 +109,9 @@ markdown_extensions:
extra:
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/typer
link: https://github.com/tiangolo/fastapi
- icon: fontawesome/brands/discord
link: https://discord.gg/VQjSZaeJmf
- icon: fontawesome/brands/twitter
link: https://twitter.com/tiangolo
- icon: fontawesome/brands/linkedin
@@ -115,6 +135,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /pl/
name: pl
- link: /pt/
name: pt - português
- link: /ru/

View File

@@ -98,7 +98,7 @@ FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
웹 API 대신 터미널에서 사용할 <abbr title="Command Line Interface">CLI</abbr> 앱을 만들고 있다면, <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>를 확인해 보세요.
웹 API 대신 터미널에서 사용할 <abbr title="Command Line Interface">CLI</abbr> 앱을 만들고 있다면, <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>를 확인해 보십시오.
**Typer**는 FastAPI의 동생입니다. 그리고 **FastAPI의 CLI**가 되기 위해 생겼습니다. ⌨️ 🚀
@@ -139,7 +139,7 @@ $ pip install uvicorn[standard]
### 만들기
* `main.py` 파일을 만드세요:
* `main.py` 파일을 만드십시오:
```Python
from typing import Optional
@@ -162,7 +162,7 @@ def read_item(item_id: int, q: Optional[str] = None):
<details markdown="1">
<summary>또는 <code>async def</code> 사용하기...</summary>
여러분의 코드가 `async` / `await`을 사용한다면, `async def`를 사용하세요:
여러분의 코드가 `async` / `await`을 사용한다면, `async def`를 사용하십시오.
```Python hl_lines="9 14"
from typing import Optional
@@ -184,7 +184,7 @@ async def read_item(item_id: int, q: Optional[str] = None):
**Note**:
잘 모르겠다면, <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">문서에서 `async`와 `await`</a>에 관한 _"급하세요?"_ 섹션을 확인해 보세요.
잘 모르겠다면, <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">문서에서 `async`와 `await`</a>에 관한 _"급하세요?"_ 섹션을 확인해 보십시오.
</details>
@@ -213,13 +213,13 @@ INFO: Application startup complete.
* `main`: `main.py` 파일 (파이썬 "모듈").
* `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
* `--reload`: 코드가 변경된 후 서버 재시작하기. 개발환경에서만 사용하세요.
* `--reload`: 코드가 변경된 후 서버 재시작하기. 개발환경에서만 사용하십시오.
</details>
### 확인하기
브라우저로 <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>를 열어보세요.
브라우저로 <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>를 열어보십시오.
아래의 JSON 응답을 볼 수 있습니다:
@@ -244,13 +244,13 @@ INFO: Application startup complete.
### 대안 API 문서
그리고 이제 <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>로 가보세요.
그리고 이제 <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>로 가봅시다.
다른 자동 문서를 볼 수 있습니다(<a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a> 제공):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## 예제 개선
## 예제 심화
이제 `PUT` 요청에 있는 본문(Body)을 받기 위해 `main.py`를 수정해봅시다.
@@ -314,7 +314,7 @@ def update_item(item_id: int, item: Item):
### 요약
요약하면, 여러분은 매개변수의 타입, 본문 등을 함수 매개변수로 **한번에** 선언했습니다.
요약하면, 여러분은 매개변수의 타입, 본문 등을 함수 매개변수로 **한번에** 선언했습니다.
여러분은 현대 표준 파이썬 타입으로 이를 행했습니다.
@@ -375,7 +375,7 @@ item: Item
* `price`을 필수 속성으로 갖고 `float` 형인지 검사.
* 만약 주어진다면, `is_offer`를 선택 속성으로 갖고 `bool` 형인지 검사.
* 이 모든 것은 깊이 중첩된 JSON 객체에도 적용됩니다.
* JSON으로, 그리고 에서부터 자동 변환.
* JSON을 변환하거나 JSON으로 변환하는 것을 자동화.
* 다음에서 사용할 수 있는 모든 것을 OpenAPI로 문서화:
* 대화형 문서 시스템.
* 여러 언어들에 대한 자동 클라이언트 코드 생성 시스템.
@@ -403,11 +403,11 @@ item: Item
... "item_price": item.price ...
```
...그러고 나서 여러분의 편집기가 속성과 타입을 알고 자동 완성하는지 보세요:
...그러고 나서 여러분의 편집기가 속성과 타입을 알고 자동 완성하는지 보십시오:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
더 많은 기능을 포함한 보다 완전한 예제의 경우, <a href="https://fastapi.tiangolo.com/tutorial/">튜토리얼 - 사용자 가이드</a>를 보세요.
더 많은 기능을 포함한 보다 완전한 예제의 경우, <a href="https://fastapi.tiangolo.com/tutorial/">튜토리얼 - 사용자 가이드</a>를 보십시오.
**스포일러 주의**: 튜토리얼 - 사용자 가이드는:
@@ -428,9 +428,9 @@ item: Item
독립된 TechEmpower 벤치마크에서 Uvicorn에서 작동하는 FastAPI 어플리케이션이 <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">사용 가능한 가장 빠른 프레임워크 중 하나</a>로 Starlette와 Uvicorn(FastAPI에서 내부적으로 사용)에만 밑돌고 있습니다. (*)
자세한 내용은 <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">벤치마크</a> 섹션을 보세요.
자세한 내용은 <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">벤치마크</a> 섹션을 보십시오.
## 선택가능한 종속사항
## 선택가능한 의존성
Pydantic이 사용하는:

View File

@@ -0,0 +1,333 @@
# 첫걸음
가장 단순한 FastAPI 파일은 다음과 같이 보일 겁니다:
```Python
{!../../../docs_src/first_steps/tutorial001.py!}
```
위를 `main.py`에 복사합니다.
라이브 서버를 실행합니다:
<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 "참고"
`uvicorn main:app` 명령은 다음을 의미합니다:
* `main`: 파일 `main.py` (파이썬 "모듈").
* `app`: `main.py` 내부의 `app = FastAPI()` 줄에서 생성한 오브젝트.
* `--reload`: 코드 변경 후 서버 재시작. 개발에만 사용.
출력에 아래와 같은 줄이 있습니다:
```hl_lines="4"
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
해당 줄은 로컬에서 앱이 서비스되는 URL을 보여줍니다.
### 확인하기
브라우저로 <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>를 여세요.
아래와 같은 JSON 응답을 볼 수 있습니다:
```JSON
{"message": "Hello World"}
```
### 대화형 API 문서
이제 <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>로 가봅니다.
자동 대화형 API 문서를 볼 수 있습니다 (<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)
### 대안 API 문서
그리고 이제, <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>로 가봅니다.
대안 자동 문서를 볼 수 있습니다 (<a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a> 제공):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
### OpenAPI
**FastAPI**는 API를 정의하기 위한 **OpenAPI** 표준을 사용하여 여러분의 모든 API를 이용해 "스키마"를 생성합니다.
#### "스키마"
"스키마"는 무언가의 정의 또는 설명입니다. 이를 구현하는 코드가 아니라 추상적인 설명일 뿐입니다.
#### API "스키마"
이 경우, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a>는 API의 스키마를 어떻게 정의하는지 지시하는 규격입니다.
이 스키마 정의는 API 경로, 가능한 매개변수 등을 포함합니다.
#### 데이터 "스키마"
"스키마"라는 용어는 JSON처럼 어떤 데이터의 형태를 나타낼 수도 있습니다.
이러한 경우 JSON 속성, 가지고 있는 데이터 타입 등을 뜻합니다.
#### OpenAPI와 JSON 스키마
OpenAPI는 API에 대한 API 스키마를 정의합니다. 또한 이 스키마에는 JSON 데이터 스키마의 표준인 **JSON 스키마**를 사용하여 API에서 보내고 받은 데이터의 정의(또는 "스키마")를 포함합니다.
#### `openapi.json` 확인
가공되지 않은 OpenAPI 스키마가 어떻게 생겼는지 궁금하다면, FastAPI는 자동으로 API의 설명과 함께 JSON (스키마)를 생성합니다.
여기에서 직접 볼 수 있습니다: <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
다음과 같이 시작하는 JSON을 확인할 수 있습니다:
```JSON
{
"openapi": "3.0.2",
"info": {
"title": "FastAPI",
"version": "0.1.0"
},
"paths": {
"/items/": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
...
```
#### OpenAPI의 용도
OpenAPI 스키마는 포함된 두 개의 대화형 문서 시스템을 제공합니다.
그리고 OpenAPI의 모든 것을 기반으로 하는 수십 가지 대안이 있습니다. **FastAPI**로 빌드한 애플리케이션에 이러한 대안을 쉽게 추가 할 수 있습니다.
API와 통신하는 클라이언트를 위해 코드를 자동으로 생성하는 데도 사용할 수 있습니다. 예로 프론트엔드, 모바일, IoT 애플리케이션이 있습니다.
## 단계별 요약
### 1 단계: `FastAPI` 임포트
```Python hl_lines="1"
{!../../../docs_src/first_steps/tutorial001.py!}
```
`FastAPI`는 API에 대한 모든 기능을 제공하는 파이썬 클래스입니다.
!!! note "기술 세부사항"
`FastAPI`는 `Starlette`를 직접 상속하는 클래스입니다.
`FastAPI`로 <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>의 모든 기능을 사용할 수 있습니다.
### 2 단계: `FastAPI` "인스턴스" 생성
```Python hl_lines="3"
{!../../../docs_src/first_steps/tutorial001.py!}
```
여기 있는 `app` 변수는 `FastAPI` 클래스의 "인스턴스"가 됩니다.
이것은 모든 API를 생성하기 위한 상호작용의 주요 지점이 될 것입니다.
이 `app`은 다음 명령에서 `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>
아래처럼 앱을 만든다면:
```Python hl_lines="3"
{!../../../docs_src/first_steps/tutorial002.py!}
```
이를 `main.py` 파일에 넣고, `uvicorn`을 아래처럼 호출해야 합니다:
<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>
### 3 단계: *경로 동작* 생성
#### 경로
여기서 "경로"는 첫 번째 `/`에서 시작하는 URL의 마지막 부분을 나타냅니다.
그러므로 아래와 같은 URL에서:
```
https://example.com/items/foo
```
...경로는 다음과 같습니다:
```
/items/foo
```
!!! info "정보"
"경로"는 일반적으로 "앤드포인트" 또는 "라우트"라고도 불립니다.
API를 빌드하는 동안 "경로"는 "관심사"와 "리소스"를 분리하는 주요 방법입니다.
#### 동작
여기서 "동작(Operation)"은 HTTP "메소드" 중 하나를 나타냅니다.
다음 중 하나이며:
* `POST`
* `GET`
* `PUT`
* `DELETE`
...이국적인 것들도 있습니다:
* `OPTIONS`
* `HEAD`
* `PATCH`
* `TRACE`
HTTP 프로토콜에서는 이러한 "메소드"를 하나(또는 이상) 사용하여 각 경로와 통신할 수 있습니다.
---
API를 빌드하는 동안 일반적으로 특정 행동을 수행하기 위해 특정 HTTP 메소드를 사용합니다.
일반적으로 다음을 사용합니다:
* `POST`: 데이터를 생성하기 위해.
* `GET`: 데이터를 읽기 위해.
* `PUT`: 데이터를 업데이트하기 위해.
* `DELETE`: 데이터를 삭제하기 위해.
그래서 OpenAPI에서는 각 HTTP 메소드들을 "동작"이라 부릅니다.
이제부터 우리는 메소드를 "**동작**"이라고도 부를겁니다.
#### *경로 동작 데코레이터* 정의
```Python hl_lines="6"
{!../../../docs_src/first_steps/tutorial001.py!}
```
`@app.get("/")`은 **FastAPI**에게 바로 아래에 있는 함수가 다음으로 이동하는 요청을 처리한다는 것을 알려줍니다.
* 경로 `/`
* <abbr title="HTTP GET 메소드"><code>get</code> 동작</abbr> 사용
!!! info "`@decorator` 정보"
이 `@something` 문법은 파이썬에서 "데코레이터"라 부릅니다.
함수 맨 위에 놓습니다. 마치 예쁜 장식용(Decorative) 모자처럼(개인적으로 이 용어가 여기서 유래한거 같습니다).
"데코레이터" 아래 있는 함수를 받고 그걸 이용해 무언가 합니다.
우리의 경우, 이 데코레이터는 **FastAPI**에게 아래 함수가 **경로** `/`에 해당하는 `get` **동작**하라고 알려줍니다.
이것이 "**경로 동작 데코레이터**"입니다.
다른 동작도 쓸 수 있습니다:
* `@app.post()`
* `@app.put()`
* `@app.delete()`
이국적인 것들도 있습니다:
* `@app.options()`
* `@app.head()`
* `@app.patch()`
* `@app.trace()`
!!! tip "팁"
각 동작(HTTP 메소드)을 원하는 대로 사용해도 됩니다.
**FastAPI**는 특정 의미를 강제하지 않습니다.
여기서 정보는 지침서일뿐 요구사항이 아닙니다.
예를 들어 GraphQL을 사용할때 일반적으로 `POST` 동작만 사용하여 모든 행동을 수행합니다.
### 4 단계: **경로 동작 함수** 정의
다음은 우리의 "**경로 동작 함수**"입니다:
* **경로**: 는 `/`입니다.
* **동작**: 은 `get`입니다.
* **함수**: 는 "데코레이터" 아래에 있는 함수입니다 (`@app.get("/")` 아래).
```Python hl_lines="7"
{!../../../docs_src/first_steps/tutorial001.py!}
```
이것은 파이썬 함수입니다.
`GET` 동작을 사용하여 URL "`/`"에 대한 요청을 받을 때마다 **FastAPI**에 의해 호출됩니다.
위의 경우 `async` 함수입니다.
---
`async def` 대신 일반 함수로 정의할 수 있습니다:
```Python hl_lines="7"
{!../../../docs_src/first_steps/tutorial003.py!}
```
!!! note 참고
차이점을 모르겠다면 [Async: *"In a hurry?"*](../async.md#in-a-hurry){.internal-link target=_blank}을 확인하세요.
### 5 단계: 콘텐츠 반환
```Python hl_lines="8"
{!../../../docs_src/first_steps/tutorial001.py!}
```
`dict`, `list`, 단일값을 가진 `str`, `int` 등을 반환할 수 있습니다.
Pydantic 모델을 반환할 수도 있습니다(나중에 더 자세히 살펴봅니다).
JSON으로 자동 변환되는 객체들과 모델들이 많이 있습니다(ORM 등을 포함해서요). 가장 마음에 드는 것을 사용하세요, 이미 지원되고 있을 겁니다.
## 요약
* `FastAPI` 임포트.
* `app` 인스턴스 생성.
* (`@app.get("/")`처럼) **경로 동작 데코레이터** 작성.
* (위에 있는 `def root(): ...`처럼) **경로 동작 함수** 작성.
* (`uvicorn main:app --reload`처럼) 개발 서버 실행.

View File

@@ -0,0 +1,90 @@
# 헤더 매개변수
헤더 매개변수를 `Query`, `Path` 그리고 `Cookie` 매개변수들과 같은 방식으로 정의할 수 있습니다.
## `Header` 임포트
먼저 `Header`를 임포트합니다:
```Python hl_lines="3"
{!../../../docs_src/header_params/tutorial001.py!}
```
## `Header` 매개변수 선언
`Path`, `Query` 그리고 `Cookie`를 사용한 동일한 구조를 이용하여 헤더 매개변수를 선언합니다.
첫 번째 값은 기본값이며, 추가 검증이나 어노테이션 매개변수 모두 전달할 수 있습니다:
```Python hl_lines="9"
{!../../../docs_src/header_params/tutorial001.py!}
```
!!! note "기술 세부사항"
`Header`는 `Path`, `Query` 및 `Cookie`의 "자매"클래스입니다. 이 역시 동일한 공통 `Param` 클래스를 상속합니다.
`Query`, `Path`, `Header` 그리고 다른 것들을 `fastapi`에서 임포트 할 때, 이들은 실제로 특별한 클래스를 반환하는 함수임을 기억하세요.
!!! info "정보"
헤더를 선언하기 위해서 `Header`를 사용해야 합니다. 그렇지 않으면 해당 매개변수를 쿼리 매개변수로 해석하기 때문입니다.
## 자동 변환
`Header`는 `Path`, `Query` 그리고 `Cookie`가 제공하는 것 외에 기능이 조금 더 있습니다.
대부분의 표준 헤더는 "마이너스 기호" (`-`)라고도 하는 "하이픈" 문자로 구분됩니다.
그러나 파이썬에서 `user-agent`와 같은 형태의 변수는 유효하지 않습니다.
따라서 `Header`는 기본적으로 매개변수 이름을 언더스코어(`_`)에서 하이픈(`-`)으로 변환하여 헤더를 추출하고 기록합니다.
또한 HTTP 헤더는 대소문자를 구분하지 않으므로 "snake_case"로 알려진 표준 파이썬 스타일로 선언할 수 있습니다.
따라서, `User_Agent` 등과 같이 첫 문자를 대문자화할 필요없이 파이썬 코드에서처럼 `user_agent`로 사용합니다.
만약 언더스코어를 하이픈으로 자동 변환을 비활성화해야 할 어떤 이유가 있다면, `Header`의 `convert_underscores` 매개변수를 `False`로 설정하십시오:
```Python hl_lines="10"
{!../../../docs_src/header_params/tutorial002.py!}
```
!!! warning "경고"
`convert_underscore`를 `False`로 설정하기 전에, 어떤 HTTP 프록시들과 서버들은 언더스코어가 포함된 헤더 사용을 허락하지 않는다는 것을 명심하십시오.
## 중복 헤더
중복 헤더들을 수신할 수 있습니다. 즉, 다중값을 갖는 동일한 헤더를 뜻합니다.
타입 정의에서 리스트를 사용하여 이러한 케이스를 정의할 수 있습니다.
중복 헤더의 모든 값을 파이썬 `list`로 수신합니다.
예를 들어, 두 번 이상 나타날 수 있는 `X-Token`헤더를 선언하려면, 다음과 같이 작성합니다:
```Python hl_lines="9"
{!../../../docs_src/header_params/tutorial003.py!}
```
다음과 같은 두 개의 HTTP 헤더를 전송하여 해당 *경로* 와 통신할 경우:
```
X-Token: foo
X-Token: bar
```
응답은 다음과 같습니다:
```JSON
{
"X-Token values": [
"bar",
"foo"
]
}
```
## 요약
`Header`는 `Query`, `Path`, `Cookie`와 동일한 패턴을 사용하여 선언합니다.
변수의 언더스코어를 걱정하지 마십시오, **FastAPI**가 변수를 변환할 것입니다.

View File

@@ -0,0 +1,80 @@
# 자습서 - 사용자 안내서 - 도입부
이 자습서는 **FastAPI**의 대부분의 기능을 단계별로 사용하는 방법을 보여줍니다.
각 섹션은 이전 섹션을 기반해서 점진적으로 만들어 졌지만, 주제를 구분하여 구성 되었기 때문에 특정 API 요구사항을 해결하기 위해 어떤 특정 항목이던지 직접 이동할 수 있습니다.
또한 향후 참조가 될 수 있도록 만들어졌습니다.
그러므로 다시 돌아와서 정확히 필요한 것을 볼 수 있습니다.
## 코드 실행하기
모든 코드 블록은 복사하고 직접 사용할 수 있습니다(실제로 테스트한 파이썬 파일입니다).
예제를 실행하려면 코드를 `main.py` 파일에 복사하고 다음을 사용하여 `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)
<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>
코드를 작성하거나 복사, 편집할 때, 로컬에서 실행하는 것을 **강력히 장려**합니다.
편집기에서 이렇게 사용하면, 모든 타입 검사, 자동완성 등 작성해야 하는 코드가 얼마나 적은지 보면서 FastAPI의 장점을 실제로 확인할 수 있습니다.
---
## FastAPI 설치
첫 번째 단계는 FastAPI 설치입니다.
자습시에는 모든 선택적인 의존성 및 기능을 사용하여 설치할 수 있습니다:
<div class="termy">
```console
$ pip install fastapi[all]
---> 100%
```
</div>
...코드를 실행하는 서버로 사용할 수 있는 `uvicorn` 역시 포함하고 있습니다.
!!! note "참고"
부분적으로 설치할 수도 있습니다.
애플리케이션을 운영 환경에 배포하려는 경우 다음과 같이 합니다:
```
pip install fastapi
```
추가로 서버 역할을 하는 `uvicorn`을 설치합니다:
```
pip install uvicorn
```
사용하려는 각 선택적인 의존성에 대해서도 동일합니다.
## 고급 사용자 안내서
**자습서 - 사용자 안내서** 다음에 읽을 수 있는 **고급 사용자 안내서**도 있습니다.
**고급 사용자 안내서**는 현재 문서를 기반으로 하고, 동일한 개념을 사용하며, 추가 기능들을 알려줍니다.
하지만 (지금 읽고 있는) **자습서 - 사용자 안내서**를 먼저 읽는게 좋습니다.
**자습서 - 사용자 안내서**만으로 완전한 애플리케이션을 구축한 다음, **고급 사용자 안내서**의 몇 가지 추가 아이디어를 사용하여 필요에 따라 다양한 방식으로 확장할 수 있도록 설계되었습니다.

View File

@@ -0,0 +1,244 @@
# 경로 매개변수
파이썬 포맷 문자열이 사용하는 동일한 문법으로 "매개변수" 또는 "변수"를 경로에 선언할 수 있습니다:
```Python hl_lines="6-7"
{!../../../docs_src/path_params/tutorial001.py!}
```
경로 매개변수 `item_id`의 값은 함수의 `item_id` 인자로 전달됩니다.
그래서 이 예제를 실행하고 <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>로 이동하면, 다음 응답을 볼 수 있습니다:
```JSON
{"item_id":"foo"}
```
## 타입이 있는 매개변수
파이썬 표준 타입 어노테이션을 사용하여 함수에 있는 경로 매개변수의 타입을 선언할 수 있습니다:
```Python hl_lines="7"
{!../../../docs_src/path_params/tutorial002.py!}
```
지금과 같은 경우, `item_id`는 `int`로 선언 되었습니다.
!!! check "확인"
이 기능은 함수 내에서 오류 검사, 자동완성 등을 편집기를 지원합니다
## 데이터 <abbr title="다음으로도 알려져 있습니다: 직렬화, 파싱, 마샬링">변환</abbr>
이 예제를 실행하고 <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a>을 열면, 다음 응답을 볼 수 있습니다:
```JSON
{"item_id":3}
```
!!! check "확인"
함수가 받은(반환도 하는) 값은 문자열 `"3"`이 아니라 파이썬 `int` 형인 `3`입니다.
즉, 타입 선언을 하면 **FastAPI**는 자동으로 요청을 <abbr title="HTTP 요청에서 전달되는 문자열을 파이썬 데이터로 변환">"파싱"</abbr>합니다.
## 데이터 검증
하지만 브라우저에서 <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>로 이동하면, 멋진 HTTP 오류를 볼 수 있습니다:
```JSON
{
"detail": [
{
"loc": [
"path",
"item_id"
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
```
경로 매개변수 `item_id`는 `int`가 아닌 `"foo"` 값이기 때문입니다.
`int` 대신 `float`을 전달하면 동일한 오류가 나타납니다: <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 "확인"
즉, 파이썬 타입 선언을 하면 **FastAPI**는 데이터 검증을 합니다.
오류는 검증을 통과하지 못한 지점도 정확하게 명시합니다.
이는 API와 상호 작용하는 코드를 개발하고 디버깅하는 데 매우 유용합니다.
## 문서화
그리고 브라우저에서 <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>를 열면, 다음과 같이 자동 대화식 API 문서를 볼 수 있습니다:
<img src="/img/tutorial/path-params/image01.png">
!!! check "확인"
다시 한번, 그저 파이썬 타입 선언을 하기만 하면 **FastAPI**는 자동 대화식 API 문서(Swagger UI 통합)를 제공합니다.
경로 매개변수는 정수형으로 선언됐음을 주목하세요.
## 표준 기반의 이점, 대체 문서화
그리고 생성된 스키마는 <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md" class="external-link" target="_blank">OpenAPI</a> 표준에서 나온 것이기 때문에 호환되는 도구가 많이 있습니다.
이 덕분에 **FastAPI**는 <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>로 접속할 수 있는 (ReDoc을 사용하는) 대체 API 문서를 제공합니다:
<img src="/img/tutorial/path-params/image02.png">
이와 마찬가지로 호환되는 도구가 많이 있습니다. 다양한 언어에 대한 코드 생성 도구를 포함합니다.
## Pydantic
모든 데이터 검증은 <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a>에 의해 내부적으로 수행되므로 이로 인한 모든 이점을 얻을 수 있습니다. 여러분은 관리를 잘 받고 있음을 느낄 수 있습니다.
`str`, `float`, `bool`과 다른 복잡한 데이터 타입 선언을 할 수 있습니다.
이 중 몇 가지는 자습서의 다음 장에서 살펴봅니다.
## 순서 문제
*경로 동작*을 만들때 고정 경로를 갖고 있는 상황들을 맞닦뜨릴 수 있습니다.
`/users/me`처럼, 현재 사용자의 데이터를 가져온다고 합시다.
사용자 ID를 이용해 특정 사용자의 정보를 가져오는 경로 `/users/{user_id}`도 있습니다.
*경로 동작*은 순차적으로 평가되기 때문에 `/users/{user_id}` 이전에 `/users/me`를 먼저 선언해야 합니다:
```Python hl_lines="6 11"
{!../../../docs_src/path_params/tutorial003.py!}
```
그렇지 않으면 `/users/{user_id}`는 매개변수 `user_id`의 값을 `"me"`라고 "생각하여" `/users/me`도 연결합니다.
## 사전정의 값
만약 *경로 매개변수*를 받는 *경로 동작*이 있지만, 유효하고 미리 정의할 수 있는 *경로 매개변수* 값을 원한다면 파이썬 표준 <abbr title="열거형(Enumeration)">`Enum`</abbr>을 사용할 수 있습니다.
### `Enum` 클래스 생성
`Enum`을 임포트하고 `str`과 `Enum`을 상속하는 서브 클래스를 만듭니다.
`str`을 상속함으로써 API 문서는 값이 `string` 형이어야 하는 것을 알게 되고 제대로 렌더링 할 수 있게 됩니다.
고정값으로 사용할 수 있는 유효한 클래스 어트리뷰트를 만듭니다:
```Python hl_lines="1 6-9"
{!../../../docs_src/path_params/tutorial005.py!}
```
!!! info "정보"
<a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">열거형(또는 enums)</a>은 파이썬 버전 3.4 이후로 사용가능합니다.
!!! tip "팁"
혹시 헷갈린다면, "AlexNet", "ResNet", 그리고 "LeNet"은 그저 기계 학습 <abbr title="기술적으로 정확히는 딥 러닝 모델 구조">모델</abbr>들의 이름입니다.
### *경로 매개변수* 선언
생성한 열거형 클래스(`ModelName`)를 사용하는 타입 어노테이션으로 *경로 매개변수*를 만듭니다:
```Python hl_lines="16"
{!../../../docs_src/path_params/tutorial005.py!}
```
### 문서 확인
*경로 매개변수*에 사용할 수 있는 값은 미리 정의되어 있으므로 대화형 문서에서 멋지게 표시됩니다:
<img src="/img/tutorial/path-params/image03.png">
### 파이썬 *열거형*으로 작업하기
*경로 매개변수*의 값은 *열거형 멤버*가 됩니다.
#### *열거형 멤버* 비교
열거체 `ModelName`의 *열거형 멤버*를 비교할 수 있습니다:
```Python hl_lines="17"
{!../../../docs_src/path_params/tutorial005.py!}
```
#### *열거형 값* 가져오기
`model_name.value` 또는 일반적으로 `your_enum_member.value`를 이용하여 실제값(지금의 경우 `str`)을 가져올 수 있습니다:
```Python hl_lines="20"
{!../../../docs_src/path_params/tutorial005.py!}
```
!!! tip "팁"
`ModelName.lenet.value`로도 값 `"lenet"`에 접근할 수 있습니다.
#### *열거형 멤버* 반환
*경로 동작*에서 중첩 JSON 본문(예: `dict`) 역시 *열거형 멤버*를 반환할 수 있습니다.
클라이언트에 반환하기 전에 해당 값(이 경우 문자열)으로 변환됩니다:
```Python hl_lines="18 21 23"
{!../../../docs_src/path_params/tutorial005.py!}
```
클라이언트는 아래의 JSON 응답을 얻습니다:
```JSON
{
"model_name": "alexnet",
"message": "Deep Learning FTW!"
}
```
## 경로를 포함하는 경로 매개변수
`/files/{file_path}`가 있는 *경로 동작*이 있다고 해봅시다.
그런데 여러분은 `home/johndoe/myfile.txt`처럼 *path*에 들어있는 `file_path` 자체가 필요합니다.
따라서 해당 파일의 URL은 다음처럼 됩니다: `/files/home/johndoe/myfile.txt`.
### OpenAPI 지원
테스트와 정의가 어려운 시나리오로 이어질 수 있으므로 OpenAPI는 *경로*를 포함하는 *경로 매개변수*를 내부에 선언하는 방법을 지원하지 않습니다.
그럼에도 Starlette의 내부 도구중 하나를 사용하여 **FastAPI**에서는 할 수 있습니다.
매개변수에 경로가 포함되어야 한다는 문서를 추가하지 않아도 문서는 계속 작동합니다.
### 경로 변환기
Starlette에서 직접 옵션을 사용하면 다음과 같은 URL을 사용하여 *path*를 포함하는 *경로 매개변수*를 선언 할 수 있습니다:
```
/files/{file_path:path}
```
이러한 경우 매개변수의 이름은 `file_path`이고 마지막 부분 `:path`는 매개변수가 *경로*와 일치해야함을 알려줍니다.
그러므로 다음과 같이 사용할 수 있습니다:
```Python hl_lines="6"
{!../../../docs_src/path_params/tutorial004.py!}
```
!!! tip "팁"
매개변수가 `/home/johndoe/myfile.txt`를 갖고 있어 슬래시로 시작(`/`)해야 할 수 있습니다.
이 경우 URL은: `/files//home/johndoe/myfile.txt`이며 `files`과 `home` 사이에 이중 슬래시(`//`)가 생깁니다.
## 요약
**FastAPI**과 함께라면 짧고 직관적인 표준 파이썬 타입 선언을 사용하여 다음을 얻을 수 있습니다:
* 편집기 지원: 오류 검사, 자동완성 등
* 데이터 "<abbr title="HTTP 요청에서 전달되는 문자열을 파이썬 데이터로 변환">파싱</abbr>"
* 데이터 검증
* API 주석(Annotation)과 자동 문서
위 사항들을 그저 한번에 선언하면 됩니다.
이는 (원래 성능과는 별개로) 대체 프레임워크와 비교했을 때 **FastAPI**의 주요 가시적 장점일 것입니다.

View File

@@ -0,0 +1,198 @@
# 쿼리 매개변수
경로 매개변수의 일부가 아닌 다른 함수 매개변수를 선언할 때, "쿼리" 매개변수로 자동 해석합니다.
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial001.py!}
```
쿼리는 URL에서 `?` 후에 나오고 `&`으로 구분되는 키-값 쌍의 집합입니다.
예를 들어, URL에서:
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
...쿼리 매개변수는:
* `skip`: 값 `0`을 가집니다.
* `limit`: 값 `10`을 가집니다.
URL의 일부이므로 "자연스럽게" 문자열입니다.
하지만 파이썬 타입과 함께 선언할 경우(위 예에서 `int`), 해당 타입으로 변환되고 이에 대해 검증합니다.
경로 매개변수에 적용된 동일한 프로세스가 쿼리 매개변수에도 적용됩니다:
* (당연히) 편집기 지원
* 데이터 <abbr title="HTTP 요청에서 전달되는 문자열을 파이썬 데이터로 변환">"파싱"</abbr>
* 데이터 검증
* 자동 문서화
## 기본값
쿼리 매개변수는 경로에서 고정된 부분이 아니기 때문에 선택적일 수 있고 기본값을 가질 수 있습니다.
위 예에서 `skip=0`과 `limit=10`은 기본값을 갖고 있습니다.
그러므로 URL로 이동하면:
```
http://127.0.0.1:8000/items/
```
아래로 이동한 것과 같습니다:
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
하지만 가령 아래로 이동한 경우:
```
http://127.0.0.1:8000/items/?skip=20
```
함수의 매개변수 값은 아래가 됩니다:
* `skip=20`: URL에서 지정했기 때문입니다
* `limit=10`: 기본값이기 때문입니다
## 선택적 매개변수
같은 방법으로 기본값을 `None`으로 설정하여 선택적 매개변수를 선언할 수 있습니다:
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial002.py!}
```
이 경우 함수 매개변수 `q`는 선택적이며 기본값으로 `None` 값이 됩니다.
!!! check "확인"
**FastAPI**는 `item_id`가 경로 매개변수이고 `q`는 경로 매개변수가 아닌 쿼리 매개변수라는 것을 알 정도로 충분히 똑똑합니다.
!!! note "참고"
FastAPI는 `q`가 `= None`이므로 선택적이라는 것을 인지합니다.
`Optional[str]`에 있는 `Optional`은 FastAPI(FastAPI는 `str` 부분만 사용합니다)가 사용하는게 아니지만, `Optional[str]`은 편집기에게 코드에서 오류를 찾아낼 수 있게 도와줍니다.
## 쿼리 매개변수 형변환
`bool` 형으로 선언할 수도 있고, 아래처럼 변환됩니다:
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial003.py!}
```
이 경우, 아래로 이동하면:
```
http://127.0.0.1:8000/items/foo?short=1
```
또는
```
http://127.0.0.1:8000/items/foo?short=True
```
또는
```
http://127.0.0.1:8000/items/foo?short=true
```
또는
```
http://127.0.0.1:8000/items/foo?short=on
```
또는
```
http://127.0.0.1:8000/items/foo?short=yes
```
또는 다른 어떤 변형(대문자, 첫글자만 대문자 등)이더라도 함수는 매개변수 `bool`형을 가진 `short`의 값이 `True`임을 압니다. 그렇지 않은 경우 `False`입니다.
## 여러 경로/쿼리 매개변수
여러 경로 매개변수와 쿼리 매개변수를 동시에 선언할 수 있으며 **FastAPI**는 어느 것이 무엇인지 알고 있습니다.
그리고 특정 순서로 선언할 필요가 없습니다.
매개변수들은 이름으로 감지됩니다:
```Python hl_lines="8 10"
{!../../../docs_src/query_params/tutorial004.py!}
```
## 필수 쿼리 매개변수
경로가 아닌 매개변수에 대한 기본값을 선언할 때(지금은 쿼리 매개변수만 보았습니다), 해당 매개변수는 필수적(Required)이지 않았습니다.
특정값을 추가하지 않고 선택적으로 만들기 위해선 기본값을 `None`으로 설정하면 됩니다.
그러나 쿼리 매개변수를 필수로 만들려면 기본값을 선언할 수 없습니다:
```Python hl_lines="6-7"
{!../../../docs_src/query_params/tutorial005.py!}
```
여기 쿼리 매개변수 `needy`는 `str`형인 필수 쿼리 매개변수입니다.
브라우저에서 URL을 아래처럼 연다면:
```
http://127.0.0.1:8000/items/foo-item
```
...필수 매개변수 `needy`를 넣지 않았기 때문에 아래와 같은 오류를 보게 됩니다:
```JSON
{
"detail": [
{
"loc": [
"query",
"needy"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}
```
`needy`는 필수 매개변수이므로 URL에 반드시 설정해줘야 합니다:
```
http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
```
...아래처럼 작동합니다:
```JSON
{
"item_id": "foo-item",
"needy": "sooooneedy"
}
```
그리고 물론, 일부 매개변수는 필수로, 다른 일부는 기본값을, 또 다른 일부는 선택적으로 선언할 수 있습니다:
```Python hl_lines="10"
{!../../../docs_src/query_params/tutorial006.py!}
```
이 경우 3가지 쿼리 매개변수가 있습니다:
* `needy`, 필수적인 `str`.
* `skip`, 기본값이 `0`인 `int`.
* `limit`, 선택적인 `int`.
!!! tip "팁"
[경로 매개변수](path-params.md#predefined-values){.internal-link target=_blank}와 마찬가지로 `Enum`을 사용할 수 있습니다.

View File

@@ -44,12 +44,19 @@ nav:
- it: /it/
- ja: /ja/
- ko: /ko/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
- tr: /tr/
- uk: /uk/
- zh: /zh/
- 자습서 - 사용자 안내서:
- tutorial/index.md
- tutorial/first-steps.md
- tutorial/path-params.md
- tutorial/query-params.md
- tutorial/header-params.md
markdown_extensions:
- toc:
permalink: true
@@ -69,7 +76,9 @@ markdown_extensions:
extra:
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/typer
link: https://github.com/tiangolo/fastapi
- icon: fontawesome/brands/discord
link: https://discord.gg/VQjSZaeJmf
- icon: fontawesome/brands/twitter
link: https://twitter.com/tiangolo
- icon: fontawesome/brands/linkedin
@@ -93,6 +102,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /pl/
name: pl
- link: /pt/
name: pt - português
- link: /ru/

464
docs/pl/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/pl/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/pl/
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: pl
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/
- it: /it/
- ja: /ja/
- ko: /ko/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
- tr: /tr/
- uk: /uk/
- zh: /zh/
markdown_extensions:
- toc:
permalink: true
- markdown.extensions.codehilite:
guess_lang: false
- 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: /it/
name: it - italiano
- link: /ja/
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /pl/
name: pl
- link: /pt/
name: pt - português
- link: /ru/
name: ru - русский язык
- link: /sq/
name: sq - shqip
- link: /tr/
name: tr - Türkçe
- link: /uk/
name: uk - українська мова
- link: /zh/
name: zh - 汉语
extra_css:
- https://fastapi.tiangolo.com/css/termynal.css
- https://fastapi.tiangolo.com/css/custom.css
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

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

View File

@@ -44,6 +44,7 @@ nav:
- it: /it/
- ja: /ja/
- ko: /ko/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
@@ -77,7 +78,9 @@ markdown_extensions:
extra:
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/typer
link: https://github.com/tiangolo/fastapi
- icon: fontawesome/brands/discord
link: https://discord.gg/VQjSZaeJmf
- icon: fontawesome/brands/twitter
link: https://twitter.com/tiangolo
- icon: fontawesome/brands/linkedin
@@ -101,6 +104,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /pl/
name: pl
- link: /pt/
name: pt - português
- link: /ru/

View File

@@ -44,6 +44,7 @@ nav:
- it: /it/
- ja: /ja/
- ko: /ko/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
@@ -69,7 +70,9 @@ markdown_extensions:
extra:
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/typer
link: https://github.com/tiangolo/fastapi
- icon: fontawesome/brands/discord
link: https://discord.gg/VQjSZaeJmf
- icon: fontawesome/brands/twitter
link: https://twitter.com/tiangolo
- icon: fontawesome/brands/linkedin
@@ -93,6 +96,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /pl/
name: pl
- link: /pt/
name: pt - português
- link: /ru/

View File

@@ -44,6 +44,7 @@ nav:
- it: /it/
- ja: /ja/
- ko: /ko/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
@@ -69,7 +70,9 @@ markdown_extensions:
extra:
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/typer
link: https://github.com/tiangolo/fastapi
- icon: fontawesome/brands/discord
link: https://discord.gg/VQjSZaeJmf
- icon: fontawesome/brands/twitter
link: https://twitter.com/tiangolo
- icon: fontawesome/brands/linkedin
@@ -93,6 +96,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /pl/
name: pl
- link: /pt/
name: pt - português
- link: /ru/

View File

@@ -44,6 +44,7 @@ nav:
- it: /it/
- ja: /ja/
- ko: /ko/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
@@ -69,7 +70,9 @@ markdown_extensions:
extra:
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/typer
link: https://github.com/tiangolo/fastapi
- icon: fontawesome/brands/discord
link: https://discord.gg/VQjSZaeJmf
- icon: fontawesome/brands/twitter
link: https://twitter.com/tiangolo
- icon: fontawesome/brands/linkedin
@@ -93,6 +96,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /pl/
name: pl
- link: /pt/
name: pt - português
- link: /ru/

View File

@@ -44,6 +44,7 @@ nav:
- it: /it/
- ja: /ja/
- ko: /ko/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
@@ -69,7 +70,9 @@ markdown_extensions:
extra:
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/typer
link: https://github.com/tiangolo/fastapi
- icon: fontawesome/brands/discord
link: https://discord.gg/VQjSZaeJmf
- icon: fontawesome/brands/twitter
link: https://twitter.com/tiangolo
- icon: fontawesome/brands/linkedin
@@ -93,6 +96,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /pl/
name: pl
- link: /pt/
name: pt - português
- link: /ru/

View File

@@ -0,0 +1,488 @@
# 更大的应用 - 多个文件
如果你正在开发一个应用程序或 Web API很少会将所有的内容都放在一个文件中。
**FastAPI** 提供了一个方便的工具,可以在保持所有灵活性的同时构建你的应用程序。
!!! info
如果你来自 Flask那这将相当于 Flask 的 Blueprints。
## 一个文件结构示例
假设你的文件结构如下:
```
.
├── app
│   ├── __init__.py
│   ├── main.py
│   ├── dependencies.py
│   └── routers
│   │ ├── __init__.py
│   │ ├── items.py
│   │ └── users.py
│   └── internal
│   ├── __init__.py
│   └── admin.py
```
!!! tip
上面有几个 `__init__.py` 文件:每个目录或子目录中都有一个。
这就是能将代码从一个文件导入到另一个文件的原因。
例如,在 `app/main.py` 中,你可以有如下一行:
```
from app.routers import items
```
* `app` 目录包含了所有内容。并且它有一个空文件 `app/__init__.py`因此它是一个「Python 包」「Python 模块」的集合):`app`。
* 它包含一个 `app/main.py` 文件。由于它位于一个 Python 包(一个包含 `__init__.py` 文件的目录)中,因此它是该包的一个「模块」:`app.main`。
* 还有一个 `app/dependencies.py` 文件,就像 `app/main.py` 一样,它是一个「模块」:`app.dependencies`。
* 有一个子目录 `app/routers/` 包含另一个 `__init__.py` 文件因此它是一个「Python 子包」:`app.routers`。
* 文件 `app/routers/items.py` 位于 `app/routers/` 包中,因此它是一个子模块:`app.routers.items`。
* 同样适用于 `app/routers/users.py`,它是另一个子模块:`app.routers.users`。
* 还有一个子目录 `app/internal/` 包含另一个 `__init__.py` 文件因此它是又一个「Python 子包」:`app.internal`。
* `app/internal/admin.py` 是另一个子模块:`app.internal.admin`。
<img src="https://fastapi.tiangolo.com/img/tutorial/bigger-applications/package.svg">
带有注释的同一文件结构:
```
.
├── app # 「app」是一个 Python 包
│   ├── __init__.py # 这个文件使「app」成为一个 Python 包
│   ├── main.py # 「main」模块例如 import app.main
│   ├── dependencies.py # 「dependencies」模块例如 import app.dependencies
│   └── routers # 「routers」是一个「Python 子包」
│   │ ├── __init__.py # 使「routers」成为一个「Python 子包」
│   │ ├── items.py # 「items」子模块例如 import app.routers.items
│   │ └── users.py # 「users」子模块例如 import app.routers.users
│   └── internal # 「internal」是一个「Python 子包」
│   ├── __init__.py # 使「internal」成为一个「Python 子包」
│   └── admin.py # 「admin」子模块例如 import app.internal.admin
```
## `APIRouter`
假设专门用于处理用户逻辑的文件是位于 `/app/routers/users.py` 的子模块。
你希望将与用户相关的*路径操作*与其他代码分开,以使其井井有条。
但它仍然是同一 **FastAPI** 应用程序/web API 的一部分它是同一「Python 包」的一部分)。
你可以使用 `APIRouter` 为该模块创建*路径操作*。
### 导入 `APIRouter`
你可以导入它并通过与 `FastAPI` 类相同的方式创建一个「实例」:
```Python hl_lines="1 3"
{!../../../docs_src/bigger_applications/app/routers/users.py!}
```
### 使用 `APIRouter` 的*路径操作*
然后你可以使用它来声明*路径操作*。
使用方式与 `FastAPI` 类相同:
```Python hl_lines="6 11 16"
{!../../../docs_src/bigger_applications/app/routers/users.py!}
```
你可以将 `APIRouter` 视为一个「迷你 `FastAPI`」类。
所有相同的选项都得到支持。
所有相同的 `parameters`、`responses`、`dependencies`、`tags` 等等。
!!! tip
在此示例中,该变量被命名为 `router`,但你可以根据你的想法自由命名。
我们将在主 `FastAPI` 应用中包含该 `APIRouter`,但首先,让我们来看看依赖项和另一个 `APIRouter`。
## 依赖项
我们了解到我们将需要一些在应用程序的好几个地方所使用的依赖项。
因此,我们将它们放在它们自己的 `dependencies` 模块(`app/dependencies.py`)中。
现在我们将使用一个简单的依赖项来读取一个自定义的 `X-Token` 请求首部:
```Python hl_lines="1 4-6"
{!../../../docs_src/bigger_applications/app/dependencies.py!}
```
!!! tip
我们正在使用虚构的请求首部来简化此示例。
但在实际情况下,使用集成的[安全性实用工具](./security/index.md){.internal-link target=_blank}会得到更好的效果。
## 其他使用 `APIRouter` 的模块
假设你在位于 `app/routers/items.py` 的模块中还有专门用于处理应用程序中「项目」的端点。
你具有以下*路径操作*
* `/items/`
* `/items/{item_id}`
这和 `app/routers/users.py` 的结构完全相同。
但是我们想变得更聪明并简化一些代码。
我们知道此模块中的所有*路径操作*都有相同的:
* 路径 `prefix``/items`。
* `tags`:(仅有一个 `items` 标签)。
* 额外的 `responses`。
* `dependencies`:它们都需要我们创建的 `X-Token` 依赖项。
因此,我们可以将其添加到 `APIRouter` 中,而不是将其添加到每个路径操作中。
```Python hl_lines="5-10 16 21"
{!../../../docs_src/bigger_applications/app/routers/items.py!}
```
由于每个*路径操作*的路径都必须以 `/` 开头,例如:
```Python hl_lines="1"
@router.get("/{item_id}")
async def read_item(item_id: str):
...
```
...前缀不能以 `/` 作为结尾。
因此,本例中的前缀为 `/items`。
我们还可以添加一个 `tags` 列表和额外的 `responses` 列表,这些参数将应用于此路由器中包含的所有*路径操作*。
我们可以添加一个 `dependencies` 列表,这些依赖项将被添加到路由器中的所有*路径操作*中,并将针对向它们发起的每个请求执行/解决。
!!! tip
请注意,和[*路径操作装饰器*中的依赖项](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}很类似,没有值会被传递给你的*路径操作函数*。
最终结果是项目相关的路径现在为:
* `/items/`
* `/items/{item_id}`
...如我们所愿。
* 它们将被标记为仅包含单个字符串 `"items"` 的标签列表。
* 这些「标签」对于自动化交互式文档系统(使用 OpenAPI特别有用。
* 所有的路径操作都将包含预定义的 `responses`。
* 所有的这些*路径操作*都将在自身之前计算/执行 `dependencies` 列表。
* 如果你还在一个具体的*路径操作*中声明了依赖项,**它们也会被执行**。
* 路由器的依赖项最先执行,然后是[装饰器中的 `dependencies`](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank},再然后是普通的参数依赖项。
* 你还可以添加[具有 `scopes` 的 `Security` 依赖项](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}。
!!! tip
在 `APIRouter`中具有 `dependencies` 可以用来,例如,对一整组的*路径操作*要求身份认证。即使这些依赖项并没有分别添加到每个路径操作中。
!!! check
`prefix`、`tags`、`responses` 以及 `dependencies` 参数只是(和其他很多情况一样)**FastAPI** 的一个用于帮助你避免代码重复的功能。
### 导入依赖项
这些代码位于 `app.routers.items` 模块,`app/routers/items.py` 文件中。
我们需要从 `app.dependencies` 模块即 `app/dependencies.py` 文件中获取依赖函数。
因此,我们通过 `..` 对依赖项使用了相对导入:
```Python hl_lines="3"
{!../../../docs_src/bigger_applications/app/routers/items.py!}
```
#### 相对导入如何工作
!!! tip
如果你完全了解导入的工作原理,请从下面的下一部分继续。
一个单点 `.`,例如:
```Python
from .dependencies import get_token_header
```
表示:
* 从该模块(`app/routers/items.py` 文件)所在的同一个包(`app/routers/` 目录)开始...
* 找到 `dependencies` 模块(一个位于 `app/routers/dependencies.py` 的虚构文件)...
* 然后从中导入函数 `get_token_header`。
但是该文件并不存在,我们的依赖项位于 `app/dependencies.py` 文件中。
请记住我们的程序/文件结构是怎样的:
<img src="https://fastapi.tiangolo.com/img/tutorial/bigger-applications/package.svg">
---
两个点 `..`,例如:
```Python
from ..dependencies import get_token_header
```
表示:
* 从该模块(`app/routers/items.py` 文件)所在的同一个包(`app/routers/` 目录)开始...
* 跳转到其父包(`app/` 目录)...
* 在该父包中,找到 `dependencies` 模块(位于 `app/dependencies.py` 的文件)...
* 然后从中导入函数 `get_token_header`。
正常工作了!🎉
---
同样,如果我们使用了三个点 `...`,例如:
```Python
from ...dependencies import get_token_header
```
那将意味着:
* 从该模块(`app/routers/items.py` 文件)所在的同一个包(`app/routers/` 目录)开始...
* 跳转到其父包(`app/` 目录)...
* 然后跳转到该包的父包(该父包并不存在,`app` 已经是最顶层的包 😱)...
* 在该父包中,找到 `dependencies` 模块(位于 `app/` 更上一级目录中的 `dependencies.py` 文件)...
* 然后从中导入函数 `get_token_header`。
这将引用 `app/` 的往上一级,带有其自己的 `__init __.py` 等文件的某个包。但是我们并没有这个包。因此,这将在我们的示例中引发错误。🚨
但是现在你知道了它的工作原理,因此无论它们多么复杂,你都可以在自己的应用程序中使用相对导入。🤓
### 添加一些自定义的 `tags`、`responses` 和 `dependencies`
我们不打算在每个*路径操作*中添加前缀 `/items` 或 `tags =["items"]`,因为我们将它们添加到了 `APIRouter` 中。
但是我们仍然可以添加*更多*将会应用于特定的*路径操作*的 `tags`,以及一些特定于该*路径操作*的额外 `responses`
```Python hl_lines="30-31"
{!../../../docs_src/bigger_applications/app/routers/items.py!}
```
!!! tip
最后的这个路径操作将包含标签的组合:`["items""custom"]`。
并且在文档中也会有两个响应,一个用于 `404`,一个用于 `403`。
## `FastAPI` 主体
现在,让我们来看看位于 `app/main.py` 的模块。
在这里你导入并使用 `FastAPI` 类。
这将是你的应用程序中将所有内容联结在一起的主文件。
并且由于你的大部分逻辑现在都存在于其自己的特定模块中,因此主文件的内容将非常简单。
### 导入 `FastAPI`
你可以像平常一样导入并创建一个 `FastAPI` 类。
我们甚至可以声明[全局依赖项](dependencies/global-dependencies.md){.internal-link target=_blank},它会和每个 `APIRouter` 的依赖项组合在一起:
```Python hl_lines="1 3 7"
{!../../../docs_src/bigger_applications/app/main.py!}
```
### 导入 `APIRouter`
现在,我们导入具有 `APIRouter` 的其他子模块:
```Python hl_lines="5"
{!../../../docs_src/bigger_applications/app/main.py!}
```
由于文件 `app/routers/users.py` 和 `app/routers/items.py` 是同一 Python 包 `app` 一个部分的子模块,因此我们可以使用单个点 ` .` 通过「相对导入」来导入它们。
### 导入是如何工作的
这段代码:
```Python
from .routers import items, users
```
表示:
* 从该模块(`app/main.py` 文件)所在的同一个包(`app/` 目录)开始...
* 寻找 `routers` 子包(位于 `app/routers/` 的目录)...
* 从该包中,导入子模块 `items` (位于 `app/routers/items.py` 的文件) 以及 `users` (位于 `app/routers/users.py` 的文件)...
`items` 模块将具有一个 `router` 变量(`items.router`)。这与我们在 `app/routers/items.py` 文件中创建的变量相同,它是一个 `APIRouter` 对象。
然后我们对 `users` 模块进行相同的操作。
我们也可以像这样导入它们:
```Python
from app.routers import items, users
```
!!! info
第一个版本是「相对导入」:
```Python
from .routers import items, users
```
第二个版本是「绝对导入」:
```Python
from app.routers import items, users
```
要了解有关 Python 包和模块的更多信息,请查阅<a href="https://docs.python.org/3/tutorial/modules.html" class="external-link" target="_blank">关于 Modules 的 Python 官方文档</a>。
### 避免名称冲突
我们将直接导入 `items` 子模块,而不是仅导入其 `router` 变量。
这是因为我们在 `users` 子模块中也有另一个名为 `router` 的变量。
如果我们一个接一个地导入,例如:
```Python
from .routers.items import router
from .routers.users import router
```
来自 `users` 的 `router` 将覆盖来自 `items` 中的 `router`,我们将无法同时使用它们。
因此,为了能够在同一个文件中使用它们,我们直接导入子模块:
```Python hl_lines="4"
{!../../../docs_src/bigger_applications/app/main.py!}
```
### 包含 `users` 和 `items` 的 `APIRouter`
现在,让我们来包含来自 `users` 和 `items` 子模块的 `router`。
```Python hl_lines="10-11"
{!../../../docs_src/bigger_applications/app/main.py!}
```
!!! info
`users.router` 包含了 `app/routers/users.py` 文件中的 `APIRouter`。
`items.router` 包含了 `app/routers/items.py` 文件中的 `APIRouter`。
使用 `app.include_router()`,我们可以将每个 `APIRouter` 添加到主 `FastAPI` 应用程序中。
它将包含来自该路由器的所有路由作为其一部分。
!!! note "技术细节"
实际上,它将在内部为声明在 `APIRouter` 中的每个*路径操作*创建一个*路径操作*。
所以,在幕后,它实际上会像所有的东西都是同一个应用程序一样工作。
!!! check
包含路由器时,你不必担心性能问题。
这将花费几微秒时间,并且只会在启动时发生。
因此,它不会影响性能。⚡
### 包含一个有自定义 `prefix`、`tags`、`responses` 和 `dependencies` 的 `APIRouter`
现在,假设你的组织为你提供了 `app/internal/admin.py` 文件。
它包含一个带有一些由你的组织在多个项目之间共享的管理员*路径操作*的 `APIRouter`。
对于此示例,它将非常简单。但是假设由于它是与组织中的其他项目所共享的,因此我们无法对其进行修改,以及直接在 `APIRouter` 中添加 `prefix`、`dependencies`、`tags` 等:
```Python hl_lines="3"
{!../../../docs_src/bigger_applications/app/internal/admin.py!}
```
但是我们仍然希望在包含 `APIRouter` 时设置一个自定义的 `prefix`,以便其所有*路径操作*以 `/admin` 开头,我们希望使用本项目已经有的 `dependencies` 保护它,并且我们希望它包含自定义的 `tags` 和 `responses`。
我们可以通过将这些参数传递给 `app.include_router()` 来完成所有的声明,而不必修改原始的 `APIRouter`
```Python hl_lines="14-17"
{!../../../docs_src/bigger_applications/app/main.py!}
```
这样,原始的 `APIRouter` 将保持不变,因此我们仍然可以与组织中的其他项目共享相同的 `app/internal/admin.py` 文件。
结果是在我们的应用程序中,来自 `admin` 模块的每个*路径操作*都将具有:
* `/admin` 前缀 。
* `admin` 标签。
* `get_token_header` 依赖项。
* `418` 响应。 🍵
但这只会影响我们应用中的 `APIRouter`,而不会影响使用它的任何其他代码。
因此,举例来说,其他项目能够以不同的身份认证方法使用相同的 `APIRouter`。
### 包含一个*路径操作*
我们还可以直接将*路径操作*添加到 `FastAPI` 应用中。
这里我们这样做了...只是为了表明我们可以做到🤷:
```Python hl_lines="21-23"
{!../../../docs_src/bigger_applications/app/main.py!}
```
它将与通过 `app.include_router()` 添加的所有其他*路径操作*一起正常运行。
!!! info "特别的技术细节"
**注意**:这是一个非常技术性的细节,你也许可以**直接跳过**。
---
`APIRouter` 没有被「挂载」,它们与应用程序的其余部分没有隔离。
这是因为我们想要在 OpenAPI 模式和用户界面中包含它们的*路径操作*。
由于我们不能仅仅隔离它们并独立于其余部分来「挂载」它们,因此*路径操作*是被「克隆的」(重新创建),而不是直接包含。
## 查看自动化的 API 文档
现在,使用 `app.main` 模块和 `app` 变量运行 `uvicorn`
<div class="termy">
```console
$ uvicorn app.main:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
然后打开位于 <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> 的文档。
你将看到使用了正确路径(和前缀)和正确标签的自动化 API 文档,包括了来自所有子模块的路径:
<img src="https://fastapi.tiangolo.com/img/tutorial/bigger-applications/image01.png">
## 多次使用不同的 `prefix` 包含同一个路由器
你也可以在*同一*路由器上使用不同的前缀来多次使用 `.include_router()`。
在有些场景这可能有用,例如以不同的前缀公开同一个的 API比方说 `/api/v1` 和 `/api/latest`。
这是一个你可能并不真正需要的高级用法,但万一你有需要了就能够用上。
## 在另一个 `APIRouter` 中包含一个 `APIRouter`
与在 `FastAPI` 应用程序中包含 `APIRouter` 的方式相同,你也可以在另一个 `APIRouter` 中包含 `APIRouter`,通过:
```Python
router.include_router(other_router)
```
请确保在你将 `router` 包含到 `FastAPI` 应用程序之前进行此操作,以便 `other_router` 中的`路径操作`也能被包含进来。

View File

@@ -0,0 +1,34 @@
# Cookie 参数
你可以像定义 `Query` 参数和 `Path` 参数一样来定义 `Cookie` 参数。
## 导入 `Cookie`
首先,导入 `Cookie`:
```Python hl_lines="3"
{!../../../docs_src/cookie_params/tutorial001.py!}
```
## 声明 `Cookie` 参数
声明 `Cookie` 参数的结构与声明 `Query` 参数和 `Path` 参数时相同。
第一个值是参数的默认值,同时也可以传递所有验证参数或注释参数,来校验参数:
```Python hl_lines="9"
{!../../../docs_src/cookie_params/tutorial001.py!}
```
!!! note "技术细节"
`Cookie` 、`Path` 、`Query`是兄弟类,它们都继承自公共的 `Param` 类
但请记住,当你从 `fastapi` 导入的 `Query`、`Path`、`Cookie` 或其他参数声明函数,这些实际上是返回特殊类的函数。
!!! info
你需要使用 `Cookie` 来声明 cookie 参数,否则参数将会被解释为查询参数。
## 总结
使用 `Cookie` 声明 cookie 参数,使用方式与 `Query` 和 `Path` 类似。

View File

@@ -0,0 +1,84 @@
# CORS跨域资源共享
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">CORS 或者「跨域资源共享」</a> 指浏览器中运行的前端拥有与后端通信的 JavaScript 代码,而后端处于与前端不同的「源」的情况。
## 源
源是协议(`http``https`)、域(`myapp.com``localhost``localhost.tiangolo.com`)以及端口(`80``443``8080`)的组合。
因此,这些都是不同的源:
* `http://localhost`
* `https://localhost`
* `http://localhost:8080`
即使它们都在 `localhost` 中,但是它们使用不同的协议或者端口,所以它们都是不同的「源」。
## 步骤
假设你的浏览器中有一个前端运行在 `http://localhost:8080`,并且它的 JavaScript 正在尝试与运行在 `http://localhost` 的后端通信(因为我们没有指定端口,浏览器会采用默认的端口 `80`)。
然后,浏览器会向后端发送一个 HTTP `OPTIONS` 请求,如果后端发送适当的 headers 来授权来自这个不同源(`http://localhost:8080`)的通信,浏览器将允许前端的 JavaScript 向后端发送请求。
为此,后端必须有一个「允许的源」列表。
在这种情况下,它必须包含 `http://localhost:8080`,前端才能正常工作。
## 通配符
也可以使用 `"*"`(一个「通配符」)声明这个列表,表示全部都是允许的。
但这仅允许某些类型的通信,不包括所有涉及凭据的内容:像 Cookies 以及那些使用 Bearer 令牌的授权 headers 等。
因此,为了一切都能正常工作,最好显式地指定允许的源。
## 使用 `CORSMiddleware`
你可以在 **FastAPI** 应用中使用 `CORSMiddleware` 来配置它。
* 导入 `CORSMiddleware`
* 创建一个允许的源列表(由字符串组成)。
* 将其作为「中间件」添加到你的 **FastAPI** 应用中。
你也可以指定后端是否允许:
* 凭证(授权 headersCookies 等)。
* 特定的 HTTP 方法(`POST``PUT`)或者使用通配符 `"*"` 允许所有方法。
* 特定的 HTTP headers 或者使用通配符 `"*"` 允许所有 headers。
```Python hl_lines="2 6-11 13-19"
{!../../../docs_src/cors/tutorial001.py!}
```
默认情况下,这个 `CORSMiddleware` 实现所使用的默认参数较为保守,所以你需要显式地启用特定的源、方法或者 headers以便浏览器能够在跨域上下文中使用它们。
支持以下参数:
* `allow_origins` - 一个允许跨域请求的源列表。例如 `['https://example.org', 'https://www.example.org']`。你可以使用 `['*']` 允许任何源。
* `allow_origin_regex` - 一个正则表达式字符串,匹配的源允许跨域请求。例如 `'https://.*\.example\.org'`。
* `allow_methods` - 一个允许跨域请求的 HTTP 方法列表。默认为 `['GET']`。你可以使用 `['*']` 来允许所有标准方法。
* `allow_headers` - 一个允许跨域请求的 HTTP 请求头列表。默认为 `[]`。你可以使用 `['*']` 允许所有的请求头。`Accept`、`Accept-Language`、`Content-Language` 以及 `Content-Type` 请求头总是允许 CORS 请求。
* `allow_credentials` - 指示跨域请求支持 cookies。默认是 `False`。另外,允许凭证时 `allow_origins` 不能设定为 `['*']`,必须指定源。
* `expose_headers` - 指示可以被浏览器访问的响应头。默认为 `[]`。
* `max_age` - 设定浏览器缓存 CORS 响应的最长时间,单位是秒。默认为 `600`。
中间件响应两种特定类型的 HTTP 请求……
### CORS 预检请求
这是些带有 `Origin` 和 `Access-Control-Request-Method` 请求头的 `OPTIONS` 请求。
在这种情况下,中间件将拦截传入的请求并进行响应,出于提供信息的目的返回一个使用了适当的 CORS headers 的 `200` 或 `400` 响应。
### 简单请求
任何带有 `Origin` 请求头的请求。在这种情况下,中间件将像平常一样传递请求,但是在响应中包含适当的 CORS headers。
## 更多信息
更多关于 <abbr title="Cross-Origin Resource Sharing">CORS</abbr> 的信息,请查看 <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">Mozilla CORS 文档</a>。
!!! note "技术细节"
你也可以使用 `from starlette.middleware.cors import CORSMiddleware`。
出于方便,**FastAPI** 在 `fastapi.middleware` 中为开发者提供了几个中间件。但是大多数可用的中间件都是直接来自 Starlette。

View File

@@ -0,0 +1,108 @@
# 调试
你可以在编辑器中连接调试器,例如使用 Visual Studio Code 或 PyCharm。
## 调用 `uvicorn`
在你的 FastAPI 应用中直接导入 `uvicorn` 并运行:
```Python hl_lines="1 15"
{!../../../docs_src/debugging/tutorial001.py!}
```
### 关于 `__name__ == "__main__"`
`__name__ == "__main__"` 的主要目的是使用以下代码调用文件时执行一些代码:
<div class="termy">
```console
$ python myapp.py
```
</div>
而当其它文件导入它时并不会被调用,像这样:
```Python
from myapp import app
```
#### 更多细节
假设你的文件命名为 `myapp.py`。
如果你这样运行:
<div class="termy">
```console
$ python myapp.py
```
</div>
那么文件中由 Python 自动创建的内部变量 `__name__`,会将字符串 `"__main__"` 作为值。
所以,下面这部分代码才会运行:
```Python
uvicorn.run(app, host="0.0.0.0", port=8000)
```
---
如果你是导入这个模块(文件)就不会这样。
因此,如果你的另一个文件 `importer.py` 像这样:
```Python
from myapp import app
# Some more code
```
在这种情况下,`myapp.py` 内部的自动变量不会有值为 `"__main__"` 的变量 `__name__`。
所以,下面这一行不会被执行:
```Python
uvicorn.run(app, host="0.0.0.0", port=8000)
```
!!! info
更多信息请检查 <a href="https://docs.python.org/3/library/__main__.html" class="external-link" target="_blank">Python 官方文档</a>.
## 使用你的调试器运行代码
由于是从代码直接运行的 Uvicorn 服务器,所以你可以从调试器直接调用 Python 程序(你的 FastAPI 应用)。
---
例如,你可以在 Visual Studio Code 中:
* 进入到「调试」面板。
* 「添加配置...」。
* 选中「Python」
* 运行「Python当前文件集成终端」选项的调试器。
然后它会使用你的 **FastAPI** 代码开启服务器,停在断点处,等等。
看起来可能是这样:
<img src="/img/tutorial/debugging/image01.png">
---
如果使用 Pycharm你可以
* 打开「运行」菜单。
* 选中「调试...」。
* 然后出现一个上下文菜单。
* 选择要调试的文件(本例中的 `main.py`)。
然后它会使用你的 **FastAPI** 代码开启服务器,停在断点处,等等。
看起来可能是这样:
<img src="/img/tutorial/debugging/image02.png">

View File

@@ -0,0 +1,66 @@
# 额外数据类型
到目前为止,您一直在使用常见的数据类型,如:
* `int`
* `float`
* `str`
* `bool`
但是您也可以使用更复杂的数据类型。
您仍然会拥有现在已经看到的相同的特性:
* 很棒的编辑器支持。
* 传入请求的数据转换。
* 响应数据转换。
* 数据验证。
* 自动补全和文档。
## 其他数据类型
下面是一些你可以使用的其他数据类型:
* `UUID`:
* 一种标准的 "通用唯一标识符" 在许多数据库和系统中用作ID。
* 在请求和响应中将以 `str` 表示。
* `datetime.datetime`:
* 一个 Python `datetime.datetime`.
* 在请求和响应中将表示为 ISO 8601 格式的 `str` ,比如: `2008-09-15T15:53:00+05:00`.
* `datetime.date`:
* Python `datetime.date`.
* 在请求和响应中将表示为 ISO 8601 格式的 `str` ,比如: `2008-09-15`.
* `datetime.time`:
* 一个 Python `datetime.time`.
* 在请求和响应中将表示为 ISO 8601 格式的 `str` ,比如: `14:23:55.003`.
* `datetime.timedelta`:
* 一个 Python `datetime.timedelta`.
* 在请求和响应中将表示为 `float` 代表总秒数。
* Pydantic 也允许将其表示为 "ISO 8601 时间差异编码", <a href="https://pydantic-docs.helpmanual.io/#json-serialisation" class="external-link" target="_blank">查看文档了解更多信息</a>。
* `frozenset`:
* 在请求和响应中,作为 `set` 对待:
* 在请求中,列表将被读取,消除重复,并将其转换为一个 `set`
* 在响应中 `set` 将被转换为 `list`
* 产生的模式将指定那些 `set` 的值是唯一的 (使用 JSON 模式的 `uniqueItems`)。
* `bytes`:
* 标准的 Python `bytes`
* 在请求和相应中被当作 `str` 处理。
* 生成的模式将指定这个 `str``binary` "格式"。
* `Decimal`:
* 标准的 Python `Decimal`
* 在请求和相应中被当做 `float` 一样处理。
* 您可以在这里检查所有有效的pydantic数据类型: <a href="https://pydantic-docs.helpmanual.io/usage/types" class="external-link" target="_blank">Pydantic data types</a>.
## 例子
下面是一个*路径操作*的示例,其中的参数使用了上面的一些类型。
```Python hl_lines="1 3 12-16"
{!../../../docs_src/extra_data_types/tutorial001.py!}
```
注意,函数内的参数有原生的数据类型,你可以,例如,执行正常的日期操作,如:
```Python hl_lines="18-19"
{!../../../docs_src/extra_data_types/tutorial001.py!}
```

View File

@@ -0,0 +1,91 @@
# Header 参数
你可以使用定义 `Query`, `Path``Cookie` 参数一样的方法定义 Header 参数。
## 导入 `Header`
首先导入 `Header`:
```Python hl_lines="3"
{!../../../docs_src/header_params/tutorial001.py!}
```
## 声明 `Header` 参数
然后使用和`Path`, `Query` and `Cookie` 一样的结构定义 header 参数
第一个值是默认值,你可以传递所有的额外验证或注释参数:
```Python hl_lines="9"
{!../../../docs_src/header_params/tutorial001.py!}
```
!!! note "技术细节"
`Header` 是 `Path`, `Query` 和 `Cookie` 的兄弟类型。它也继承自通用的 `Param` 类.
但是请记得,当你从`fastapi`导入 `Query`, `Path`, `Header`, 或其他时,实际上导入的是返回特定类型的函数。
!!! info
为了声明headers 你需要使用`Header`, 因为否则参数将被解释为查询参数。
## 自动转换
`Header` 在 `Path`, `Query` 和 `Cookie` 提供的功能之上有一点额外的功能。
大多数标准的headers用 "连字符" 分隔,也称为 "减号" (`-`)。
但是像 `user-agent` 这样的变量在Python中是无效的。
因此, 默认情况下, `Header` 将把参数名称的字符从下划线 (`_`) 转换为连字符 (`-`) 来提取并记录 headers.
同时HTTP headers 是大小写不敏感的因此因此可以使用标准Python样式(也称为 "snake_case")声明它们。
因此您可以像通常在Python代码中那样使用 `user_agent` ,而不需要将首字母大写为 `User_Agent` 或类似的东西。
如果出于某些原因,你需要禁用下划线到连字符的自动转换,设置`Header`的参数 `convert_underscores` 为 `False`:
```Python hl_lines="10"
{!../../../docs_src/header_params/tutorial002.py!}
```
!!! warning
在设置 `convert_underscores` 为 `False` 之前请记住一些HTTP代理和服务器不允许使用带有下划线的headers。
## 重复的 headers
有可能收到重复的headers。这意味着相同的header具有多个值。
您可以在类型声明中使用一个list来定义这些情况。
你可以通过一个Python `list` 的形式获得重复header的所有值。
比如, 为了声明一个 `X-Token` header 可以出现多次,你可以这样写:
```Python hl_lines="9"
{!../../../docs_src/header_params/tutorial003.py!}
```
如果你与*路径操作*通信时发送两个HTTP headers就像
```
X-Token: foo
X-Token: bar
```
响应会是:
```JSON
{
"X-Token values": [
"bar",
"foo"
]
}
```
## 回顾
使用 `Header` 来声明 header , 使用和 `Query`, `Path` 与 `Cookie` 相同的模式。
不用担心变量中的下划线,**FastAPI** 会负责转换它们。

View File

@@ -0,0 +1,105 @@
# 元数据和文档 URL
你可以在 **FastAPI** 应用中自定义几个元数据配置。
## 标题、描述和版本
你可以设定:
* **Title**:在 OpenAPI 和自动 API 文档用户界面中作为 API 的标题/名称使用。
* **Description**:在 OpenAPI 和自动 API 文档用户界面中用作 API 的描述。
* **Version**API 版本,例如 `v2` 或者 `2.5.0`
* 如果你之前的应用程序版本也使用 OpenAPI 会很有用。
使用 `title``description``version` 来设置它们:
```Python hl_lines="4-6"
{!../../../docs_src/metadata/tutorial001.py!}
```
通过这样设置,自动 API 文档看起来会像:
<img src="/img/tutorial/metadata/image01.png">
## 标签元数据
你也可以使用参数 `openapi_tags`,为用于分组路径操作的不同标签添加额外的元数据。
它接受一个列表,这个列表包含每个标签对应的一个字典。
每个字典可以包含:
* `name`**必要**):一个 `str`,它与*路径操作*和 `APIRouter` 中使用的 `tags` 参数有相同的标签名。
* `description`:一个用于简短描述标签的 `str`。它支持 Markdown 并且会在文档用户界面中显示。
* `externalDocs`:一个描述外部文档的 `dict`
* `description`:用于简短描述外部文档的 `str`。
* `url`**必要**):外部文档的 URL `str`。
### 创建标签元数据
让我们在带有标签的示例中为 `users` 和 `items` 试一下。
创建标签元数据并把它传递给 `openapi_tags` 参数:
```Python hl_lines="3-16 18"
{!../../../docs_src/metadata/tutorial004.py!}
```
注意你可以在描述内使用 Markdown例如「login」会显示为粗体**login**以及「fancy」会显示为斜体_fancy_
!!! 提示
不必为你使用的所有标签都添加元数据。
### 使用你的标签
将 `tags` 参数和*路径操作*(以及 `APIRouter`)一起使用,将其分配给不同的标签:
```Python hl_lines="21 26"
{!../../../docs_src/metadata/tutorial004.py!}
```
!!! 信息
阅读更多关于标签的信息[路径操作配置](../path-operation-configuration/#tags){.internal-link target=_blank}。
### 查看文档
如果你现在查看文档,它们会显示所有附加的元数据:
<img src="/img/tutorial/metadata/image02.png">
### 标签顺序
每个标签元数据字典的顺序也定义了在文档用户界面显示的顺序。
例如按照字母顺序,即使 `users` 排在 `items` 之后,它也会显示在前面,因为我们将它的元数据添加为列表内的第一个字典。
## OpenAPI URL
默认情况下OpenAPI 模式服务于 `/openapi.json`。
但是你可以通过参数 `openapi_url` 对其进行配置。
例如,将其设置为服务于 `/api/v1/openapi.json`
```Python hl_lines="3"
{!../../../docs_src/metadata/tutorial002.py!}
```
如果你想完全禁用 OpenAPI 模式,可以将其设置为 `openapi_url=None`,这样也会禁用使用它的文档用户界面。
## 文档 URLs
你可以配置两个文档用户界面,包括:
* **Swagger UI**:服务于 `/docs`。
* 可以使用参数 `docs_url` 设置它的 URL。
* 可以通过设置 `docs_url=None` 禁用它。
* ReDoc服务于 `/redoc`。
* 可以使用参数 `redoc_url` 设置它的 URL。
* 可以通过设置 `redoc_url=None` 禁用它。
例如,设置 Swagger UI 服务于 `/documentation` 并禁用 ReDoc
```Python hl_lines="3"
{!../../../docs_src/metadata/tutorial003.py!}
```

View File

@@ -0,0 +1,61 @@
# 中间件
你可以向 **FastAPI** 应用添加中间件.
"中间件"是一个函数,它在每个**请求**被特定的*路径操作*处理之前,以及在每个**响应**返回之前工作.
* 它接收你的应用程序的每一个**请求**.
* 然后它可以对这个**请求**做一些事情或者执行任何需要的代码.
* 然后它将**请求**传递给应用程序的其他部分 (通过某种*路径操作*).
* 然后它获取应用程序生产的**响应** (通过某种*路径操作*).
* 它可以对该**响应**做些什么或者执行任何需要的代码.
* 然后它返回这个 **响应**.
!!! note "技术细节"
如果你使用了 `yield` 关键字依赖, 依赖中的退出代码将在执行中间件*后*执行.
如果有任何后台任务(稍后记录), 它们将在执行中间件*后*运行.
## 创建中间件
要创建中间件你可以在函数的顶部使用装饰器 `@app.middleware("http")`.
中间件参数接收如下参数:
* `request`.
* 一个函数 `call_next` 它将接收 `request` 作为参数.
* 这个函数将 `request` 传递给相应的 *路径操作*.
* 然后它将返回由相应的*路径操作*生成的 `response`.
* 然后你可以在返回 `response` 前进一步修改它.
```Python hl_lines="8-9 11 14"
{!../../../docs_src/middleware/tutorial001.py!}
```
!!! tip
请记住可以 <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">用'X-' 前缀</a>添加专有自定义请求头.
但是如果你想让浏览器中的客户端看到你的自定义请求头, 你需要把它们加到 CORS 配置 ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) 的 `expose_headers` 参数中,在 <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette's CORS docs</a>文档中.
!!! note "技术细节"
你也可以使用 `from starlette.requests import Request`.
**FastAPI** 为了开发者方便提供了该对象. 但其实它直接来自于 Starlette.
### 在 `response` 的前和后
在任何*路径操作*收到`request`前,可以添加要和请求一起运行的代码.
也可以在*响应*生成但是返回之前添加代码.
例如你可以添加自定义请求头 `X-Process-Time` 包含以秒为单位的接收请求和生成响应的时间:
```Python hl_lines="10 12-13"
{!../../../docs_src/middleware/tutorial001.py!}
```
## 其他中间件
你可以稍后在 [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}阅读更多关于中间件的教程.
你将在下一节中学习如何使用中间件处理 <abbr title="Cross-Origin Resource Sharing">CORS</abbr> .

View File

@@ -191,36 +191,3 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
!!! tip
你还可以像在 [路径参数](path-params.md#predefined-values){.internal-link target=_blank} 中那样使用 `Enum`。
## Optional 类型声明
!!! warning
这可能是一个比较高级的使用场景。
您也可以跳过它。
如果你正在使用 `mypy`,它可能会对如下的类型声明进行警告:
```Python
limit: int = None
```
提示类似以下错误:
```
Incompatible types in assignment (expression has type "None", variable has type "int")
```
在这种情况下,你可以使用 `Optional` 来告诉 `mypy` 该值可以为 `None`,例如:
```Python
from typing import Optional
limit: Optional[int] = None
```
在一个*路径操作*中,看起来会是:
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial007.py!}
```

View File

@@ -0,0 +1,114 @@
# 获取当前用户
在上一章节中,(基于依赖项注入系统的)安全系统向*路径操作函数*提供了一个 `str` 类型的 `token`
```Python hl_lines="10"
{!../../../docs_src/security/tutorial001.py!}
```
但这还不是很实用。
让我们来使它返回当前用户给我们。
## 创建一个用户模型
首先,让我们来创建一个用户 Pydantic 模型。
与使用 Pydantic 声明请求体的方式相同,我们可以在其他任何地方使用它:
```Python hl_lines="5 12-16"
{!../../../docs_src/security/tutorial002.py!}
```
## 创建一个 `get_current_user` 依赖项
让我们来创建一个 `get_current_user` 依赖项。
还记得依赖项可以有子依赖项吗?
`get_current_user` 将具有一个我们之前所创建的同一个 `oauth2_scheme` 作为依赖项。
与我们之前直接在路径操作中所做的相同,我们新的依赖项 `get_current_user` 将从子依赖项 `oauth2_scheme` 中接收一个 `str` 类型的 `token`
```Python hl_lines="25"
{!../../../docs_src/security/tutorial002.py!}
```
## 获取用户
`get_current_user` 将使用我们创建的(伪)工具函数,该函数接收 `str` 类型的令牌并返回我们的 Pydantic `User` 模型:
```Python hl_lines="19-22 26-27"
{!../../../docs_src/security/tutorial002.py!}
```
## 注入当前用户
因此现在我们可以在*路径操作*中使用 `get_current_user` 作为 `Depends` 了:
```Python hl_lines="31"
{!../../../docs_src/security/tutorial002.py!}
```
注意我们将 `current_user` 的类型声明为 Pydantic 模型 `User`。
这将帮助我们在函数内部使用所有的代码补全和类型检查。
!!! tip
你可能还记得请求体也是使用 Pydantic 模型来声明的。
在这里 **FastAPI** 不会搞混,因为你正在使用的是 `Depends`。
!!! check
这种依赖系统的设计方式使我们可以拥有不同的依赖项(不同的「可依赖类型」),并且它们都返回一个 `User` 模型。
我们并未被局限于只能有一个返回该类型数据的依赖项。
## 其他模型
现在你可以直接在*路径操作函数*中获取当前用户,并使用 `Depends` 在**依赖注入**级别处理安全性机制。
你可以使用任何模型或数据来满足安全性要求(在这个示例中,使用的是 Pydantic 模型 `User`)。
但是你并未被限制只能使用某些特定的数据模型,类或类型。
你想要在模型中使用 `id` 和 `email` 而不使用任何的 `username`?当然可以。你可以同样地使用这些工具。
你只想要一个 `str`?或者仅仅一个 `dict`?还是直接一个数据库模型类的实例?它们的工作方式都是一样的。
实际上你没有用户登录到你的应用程序,而是只拥有访问令牌的机器人,程序或其他系统?再一次,它们的工作方式也是一样的。
尽管去使用你的应用程序所需要的任何模型,任何类,任何数据库。**FastAPI** 通过依赖项注入系统都帮你搞定。
## 代码体积
这个示例似乎看起来很冗长。考虑到我们在同一文件中混合了安全性,数据模型工具函数和路径操作等代码。
但关键的是。
安全性和依赖项注入内容只需要编写一次。
你可以根据需要使其变得很复杂。而且只需要在一个地方写一次。但仍然具备所有的灵活性。
但是,你可以有无数个使用同一安全系统的端点(*路径操作*)。
所有(或所需的任何部分)的端点,都可以利用对这些或你创建的其他依赖项进行复用所带来的优势。
所有的这无数个*路径操作*甚至可以小到只需 3 行代码:
```Python hl_lines="30-32"
{!../../../docs_src/security/tutorial002.py!}
```
## 总结
现在你可以直接在*路径操作函数*中获取当前用户。
我们已经进行到一半了。
我们只需要再为用户/客户端添加一个真正发送 `username` 和 `password` 的*路径操作*。
这些内容在下一章节。

View File

@@ -0,0 +1,101 @@
# 安全性简介
有许多方法可以处理安全性、身份认证和授权等问题。
而且这通常是一个复杂而「困难」的话题。
在许多框架和系统中,仅处理安全性和身份认证就会花费大量的精力和代码(在许多情况下,可能占编写的所有代码的 50 或更多)。
**FastAPI** 提供了多种工具,可帮助你以标准的方式轻松、快速地处理**安全性**,而无需研究和学习所有的安全规范。
但首先,让我们来看一些小的概念。
## 没有时间?
如果你不关心这些术语,而只需要*立即*通过基于用户名和密码的身份认证来增加安全性,请跳转到下一章。
## OAuth2
OAuth2是一个规范它定义了几种处理身份认证和授权的方法。
它是一个相当广泛的规范,涵盖了一些复杂的使用场景。
它包括了使用「第三方」进行身份认证的方法。
这就是所有带有「使用 FacebookGoogleTwitterGitHub 登录」的系统背后所使用的机制。
### OAuth 1
有一个 OAuth 1它与 OAuth2 完全不同,并且更为复杂,因为它直接包含了有关如何加密通信的规范。
如今它已经不是很流行,没有被广泛使用了。
OAuth2 没有指定如何加密通信,它期望你为应用程序使用 HTTPS 进行通信。
!!! tip
在有关**部署**的章节中,你将了解如何使用 Traefik 和 Let's Encrypt 免费设置 HTTPS。
## OpenID Connect
OpenID Connect 是另一个基于 **OAuth2** 的规范。
它只是扩展了 OAuth2并明确了一些在 OAuth2 中相对模糊的内容,以尝试使其更具互操作性。
例如Google 登录使用 OpenID Connect底层使用OAuth2
但是 Facebook 登录不支持 OpenID Connect。它具有自己的 OAuth2 风格。
### OpenID非「OpenID Connect」
还有一个「OpenID」规范。它试图解决与 **OpenID Connect** 相同的问题,但它不是基于 OAuth2。
因此,它是一个完整的附加系统。
如今它已经不是很流行,没有被广泛使用了。
## OpenAPI
OpenAPI以前称为 Swagger是用于构建 API 的开放规范(现已成为 Linux Foundation 的一部分)。
**FastAPI** 基于 **OpenAPI**
这就是使多个自动交互式文档界面,代码生成等成为可能的原因。
OpenAPI 有一种定义多个安全「方案」的方法。
通过使用它们,你可以利用所有这些基于标准的工具,包括这些交互式文档系统。
OpenAPI 定义了以下安全方案:
* `apiKey`:一个特定于应用程序的密钥,可以来自:
* 查询参数。
* 请求头。
* cookie。
* `http`:标准的 HTTP 身份认证系统,包括:
* `bearer`: 一个值为 `Bearer` 加令牌字符串的 `Authorization` 请求头。这是从 OAuth2 继承的。
* HTTP Basic 认证方式。
* HTTP Digest等等。
* `oauth2`:所有的 OAuth2 处理安全性的方式(称为「流程」)。
*以下几种流程适合构建 OAuth 2.0 身份认证的提供者(例如 GoogleFacebookTwitterGitHub 等):
* `implicit`
* `clientCredentials`
* `authorizationCode`
* 但是有一个特定的「流程」可以完美地用于直接在同一应用程序中处理身份认证:
* `password`:接下来的几章将介绍它的示例。
* `openIdConnect`:提供了一种定义如何自动发现 OAuth2 身份认证数据的方法。
* 此自动发现机制是 OpenID Connect 规范中定义的内容。
!!! tip
集成其他身份认证/授权提供者例如GoogleFacebookTwitterGitHub等也是可能的而且较为容易。
最复杂的问题是创建一个像这样的身份认证/授权提供程序,但是 **FastAPI** 为你提供了轻松完成任务的工具,同时为你解决了重活。
## **FastAPI** 实用工具
FastAPI 在 `fastapi.security` 模块中为每个安全方案提供了几种工具,这些工具简化了这些安全机制的使用方法。
在下一章中,你将看到如何使用 **FastAPI** 所提供的这些工具为你的 API 增加安全性。
而且你还将看到它如何自动地被集成到交互式文档系统中。

View File

@@ -0,0 +1,266 @@
# 使用(哈希)密码和 JWT Bearer 令牌的 OAuth2
既然我们已经有了所有的安全流程,就让我们来使用 <abbr title="JSON Web Tokens">JWT</abbr> 令牌和安全哈希密码让应用程序真正地安全吧。
你可以在应用程序中真正地使用这些代码,在数据库中保存密码哈希值,等等。
我们将从上一章结束的位置开始,然后对示例进行扩充。
## 关于 JWT
JWT 表示 「JSON Web Tokens」。
它是一个将 JSON 对象编码为密集且没有空格的长字符串的标准。字符串看起来像这样:
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
```
它没有被加密,因此任何人都可以从字符串内容中还原数据。
但它经过了签名。因此,当你收到一个由你发出的令牌时,可以校验令牌是否真的由你发出。
通过这种方式,你可以创建一个有效期为 1 周的令牌。然后当用户第二天使用令牌重新访问时,你知道该用户仍然处于登入状态。
一周后令牌将会过期,用户将不会通过认证,必须再次登录才能获得一个新令牌。而且如果用户(或第三方)试图修改令牌以篡改过期时间,你将因为签名不匹配而能够发觉。
如果你想上手体验 JWT 令牌并了解其工作方式,可访问 <a href="https://jwt.io/" class="external-link" target="_blank">https://jwt.io</a>。
## 安装 `python-jose`
我们需要安装 `python-jose` 以在 Python 中生成和校验 JWT 令牌:
<div class="termy">
```console
$ pip install python-jose[cryptography]
---> 100%
```
</div>
<a href="https://github.com/mpdavis/python-jose" class="external-link" target="_blank">Python-jose</a> 需要一个额外的加密后端。
这里我们使用的是推荐的后端:<a href="https://cryptography.io/" class="external-link" target="_blank">pyca/cryptography</a>。
!!! tip
本教程曾经使用过 <a href="https://pyjwt.readthedocs.io/" class="external-link" target="_blank">PyJWT</a>。
但是后来更新为使用 Python-jose因为它提供了 PyJWT 的所有功能,以及之后与其他工具进行集成时你可能需要的一些其他功能。
## 哈希密码
「哈希」的意思是:将某些内容(在本例中为密码)转换为看起来像乱码的字节序列(只是一个字符串)。
每次你传入完全相同的内容(完全相同的密码)时,你都会得到完全相同的乱码。
但是你不能从乱码转换回密码。
### 为什么使用哈希密码
如果你的数据库被盗,小偷将无法获得用户的明文密码,只能拿到哈希值。
因此,小偷将无法尝试在另一个系统中使用这些相同的密码(由于许多用户在任何地方都使用相同的密码,因此这很危险)。
## 安装 `passlib`
PassLib 是一个用于处理哈希密码的很棒的 Python 包。
它支持许多安全哈希算法以及配合算法使用的实用程序。
推荐的算法是 「Bcrypt」。
因此,安装附带 Bcrypt 的 PassLib
<div class="termy">
```console
$ pip install passlib[bcrypt]
---> 100%
```
</div>
!!! tip
使用 `passlib`,你甚至可以将其配置为能够读取 DjangoFlask 的安全扩展或许多其他工具创建的密码。
因此,你将能够,举个例子,将数据库中来自 Django 应用的数据共享给一个 FastAPI 应用。或者使用同一数据库但逐渐将应用从 Django 迁移到 FastAPI。
而你的用户将能够同时从 Django 应用或 FastAPI 应用登录。
## 哈希并校验密码
`passlib` 导入我们需要的工具。
创建一个 PassLib 「上下文」。这将用于哈希和校验密码。
!!! tip
PassLib 上下文还具有使用不同哈希算法的功能,包括仅允许用于校验的已弃用的旧算法等。
例如你可以使用它来读取和校验由另一个系统例如Django生成的密码但是使用其他算法例如 Bcrypt 生成新的密码哈希值。
并同时兼容所有的这些功能。
创建一个工具函数以哈希来自用户的密码。
然后创建另一个工具函数,用于校验接收的密码是否与存储的哈希值匹配。
再创建另一个工具函数用于认证并返回用户。
```Python hl_lines="7 48 55-56 59-60 69-75"
{!../../../docs_src/security/tutorial004.py!}
```
!!! note
如果你查看新的(伪)数据库 `fake_users_db`,你将看到哈希后的密码现在的样子:`"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`。
## 处理 JWT 令牌
导入已安装的模块。
创建一个随机密钥,该密钥将用于对 JWT 令牌进行签名。
要生成一个安全的随机密钥,可使用以下命令:
<div class="termy">
```console
$ openssl rand -hex 32
09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7
```
</div>
然后将输出复制到变量 「SECRET_KEY」 中(不要使用示例中的这个)。
创建用于设定 JWT 令牌签名算法的变量 「ALGORITHM」并将其设置为 `"HS256"`。
创建一个设置令牌过期时间的变量。
定义一个将在令牌端点中用于响应的 Pydantic 模型。
创建一个生成新的访问令牌的工具函数。
```Python hl_lines="6 12-14 28-30 78-86"
{!../../../docs_src/security/tutorial004.py!}
```
## 更新依赖项
更新 `get_current_user` 以接收与之前相同的令牌,但这次使用的是 JWT 令牌。
解码接收到的令牌,对其进行校验,然后返回当前用户。
如果令牌无效,立即返回一个 HTTP 错误。
```Python hl_lines="89-106"
{!../../../docs_src/security/tutorial004.py!}
```
## 更新 `/token` *路径操作*
使用令牌的过期时间创建一个 `timedelta` 对象。
创建一个真实的 JWT 访问令牌并返回它。
```Python hl_lines="115-128"
{!../../../docs_src/security/tutorial004.py!}
```
### 关于 JWT 「主题」 `sub` 的技术细节
JWT 的规范中提到有一个 `sub` 键,值为该令牌的主题。
使用它并不是必须的,但这是你放置用户标识的地方,所以我们在示例中使用了它。
除了识别用户并允许他们直接在你的 API 上执行操作之外JWT 还可以用于其他事情。
例如,你可以识别一个 「汽车」 或 「博客文章」。
然后你可以添加关于该实体的权限,比如「驾驶」(汽车)或「编辑」(博客)。
然后,你可以将 JWT 令牌交给用户(或机器人),他们可以使用它来执行这些操作(驾驶汽车,或编辑博客文章),甚至不需要有一个账户,只需使用你的 API 为其生成的 JWT 令牌。
使用这样的思路JWT 可以用于更复杂的场景。
在这些情况下,几个实体可能有相同的 ID比如说 `foo`(一个用户 `foo`,一辆车 `foo`,一篇博客文章 `foo`)。
因此,为了避免 ID 冲突,当为用户创建 JWT 令牌时,你可以在 `sub` 键的值前加上前缀,例如 `username:`。所以,在这个例子中,`sub` 的值可以是:`username:johndoe`。
要记住的重点是,`sub` 键在整个应用程序中应该有一个唯一的标识符,而且应该是一个字符串。
## 检查效果
运行服务器并访问文档: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>。
你会看到如下用户界面:
<img src="https://fastapi.tiangolo.com/img/tutorial/security/image07.png">
像以前一样对应用程序进行认证。
使用如下凭证:
用户名: `johndoe`
密码: `secret`
!!! check
请注意,代码中没有任何地方记录了明文密码 「`secret`」,我们只保存了其哈希值。
<img src="https://fastapi.tiangolo.com/img/tutorial/security/image08.png">
访问 `/users/me/` 端点,你将获得如下响应:
```JSON
{
"username": "johndoe",
"email": "johndoe@example.com",
"full_name": "John Doe",
"disabled": false
}
```
<img src="https://fastapi.tiangolo.com/img/tutorial/security/image09.png">
如果你打开开发者工具,将看到数据是如何发送的并且其中仅包含了令牌,只有在第一个请求中发送了密码以校验用户身份并获取该访问令牌,但之后都不会再发送密码:
<img src="https://fastapi.tiangolo.com/img/tutorial/security/image10.png">
!!! note
注意请求中的 `Authorization` 首部,其值以 `Bearer` 开头。
## 使用 `scopes` 的进阶用法
OAuth2 具有「作用域」的概念。
你可以使用它们向 JWT 令牌添加一组特定的权限。
然后,你可以将此令牌直接提供给用户或第三方,使其在一些限制下与你的 API 进行交互。
你可以在之后的**进阶用户指南**中了解如何使用它们以及如何将它们集成到 **FastAPI** 中。
## 总结
通过目前你所看到的,你可以使用像 OAuth2 和 JWT 这样的标准来构建一个安全的 **FastAPI** 应用程序。
在几乎所有的框架中,处理安全性问题都很容易成为一个相当复杂的话题。
许多高度简化了安全流程的软件包不得不在数据模型、数据库和可用功能上做出很多妥协。而这些过于简化流程的软件包中,有些其实隐含了安全漏洞。
---
**FastAPI** 不对任何数据库、数据模型或工具做任何妥协。
它给了你所有的灵活性来选择最适合你项目的前者。
你可以直接使用许多维护良好且使用广泛的包,如 `passlib` 和 `python-jose`,因为 **FastAPI** 不需要任何复杂的机制来集成外部包。
但它为你提供了一些工具,在不影响灵活性、健壮性和安全性的前提下,尽可能地简化这个过程。
而且你可以用相对简单的方式使用和实现安全、标准的协议,比如 OAuth2。
你可以在**进阶用户指南**中了解更多关于如何使用 OAuth2 「作用域」的信息,以实现更精细的权限系统,并同样遵循这些标准。带有作用域的 OAuth2 是很多大的认证提供商使用的机制,比如 Facebook、Google、GitHub、微软、Twitter 等,授权第三方应用代表用户与他们的 API 进行交互。

View File

@@ -0,0 +1,275 @@
# 使用密码和 Bearer 的简单 OAuth2
现在让我们接着上一章继续开发,并添加缺少的部分以实现一个完整的安全性流程。
## 获取 `username` 和 `password`
我们将使用 **FastAPI** 的安全性实用工具来获取 `username``password`
OAuth2 规定在使用我们打算用的「password 流程」时,客户端/用户必须将 `username``password` 字段作为表单数据发送。
而且规范明确了字段必须这样命名。因此 `user-name``email` 是行不通的。
不过不用担心,你可以在前端按照你的想法将它展示给最终用户。
而且你的数据库模型也可以使用你想用的任何其他名称。
但是对于登录*路径操作*,我们需要使用这些名称来与规范兼容(以具备例如使用集成的 API 文档系统的能力)。
规范还写明了 `username``password` 必须作为表单数据发送(因此,此处不能使用 JSON
### `scope`
规范还提到客户端可以发送另一个表单字段「`scope`」。
这个表单字段的名称为 `scope`(单数形式),但实际上它是一个由空格分隔的「作用域」组成的长字符串。
每个「作用域」只是一个字符串(中间没有空格)。
它们通常用于声明特定的安全权限,例如:
* `users:read` 或者 `users:write` 是常见的例子。
* Facebook / Instagram 使用 `instagram_basic`
* Google 使用了 `https://www.googleapis.com/auth/drive`
!!! info
在 OAuth2 中「作用域」只是一个声明所需特定权限的字符串。
它有没有 `:` 这样的其他字符或者是不是 URL 都没有关系。
这些细节是具体的实现。
对 OAuth2 来说它们就只是字符串而已。
## 获取 `username` 和 `password` 的代码
现在,让我们使用 **FastAPI** 提供的实用工具来处理此问题。
### `OAuth2PasswordRequestForm`
首先,导入 `OAuth2PasswordRequestForm`,然后在 `token` 的*路径操作*中通过 `Depends` 将其作为依赖项使用。
```Python hl_lines="4 76"
{!../../../docs_src/security/tutorial003.py!}
```
`OAuth2PasswordRequestForm` 是一个类依赖项,声明了如下的请求表单:
* `username`。
* `password`。
* 一个可选的 `scope` 字段,是一个由空格分隔的字符串组成的大字符串。
* 一个可选的 `grant_type`.
!!! tip
OAuth2 规范实际上*要求* `grant_type` 字段使用一个固定的值 `password`,但是 `OAuth2PasswordRequestForm` 没有作强制约束。
如果你需要强制要求这一点,请使用 `OAuth2PasswordRequestFormStrict` 而不是 `OAuth2PasswordRequestForm`。
* 一个可选的 `client_id`(我们的示例不需要它)。
* 一个可选的 `client_secret`(我们的示例不需要它)。
!!! info
`OAuth2PasswordRequestForm` 并不像 `OAuth2PasswordBearer` 一样是 FastAPI 的一个特殊的类。
`OAuth2PasswordBearer` 使得 **FastAPI** 明白它是一个安全方案。所以它得以通过这种方式添加到 OpenAPI 中。
但 `OAuth2PasswordRequestForm` 只是一个你可以自己编写的类依赖项,或者你也可以直接声明 `Form` 参数。
但是由于这是一种常见的使用场景,因此 FastAPI 出于简便直接提供了它。
### 使用表单数据
!!! tip
类依赖项 `OAuth2PasswordRequestForm` 的实例不会有用空格分隔的长字符串属性 `scope`,而是具有一个 `scopes` 属性,该属性将包含实际被发送的每个作用域字符串组成的列表。
在此示例中我们没有使用 `scopes`,但如果你需要的话可以使用该功能。
现在,使用表单字段中的 `username` 从(伪)数据库中获取用户数据。
如果没有这个用户,我们将返回一个错误消息,提示「用户名或密码错误」。
对于这个错误,我们使用 `HTTPException` 异常:
```Python hl_lines="3 77-79"
{!../../../docs_src/security/tutorial003.py!}
```
### 校验密码
目前我们已经从数据库中获取了用户数据,但尚未校验密码。
让我们首先将这些数据放入 Pydantic `UserInDB` 模型中。
永远不要保存明文密码,因此,我们将使用(伪)哈希密码系统。
如果密码不匹配,我们将返回同一个错误。
#### 哈希密码
「哈希」的意思是:将某些内容(在本例中为密码)转换为看起来像乱码的字节序列(只是一个字符串)。
每次你传入完全相同的内容(完全相同的密码)时,你都会得到完全相同的乱码。
但是你不能从乱码转换回密码。
##### 为什么使用哈希密码
如果你的数据库被盗,小偷将无法获得用户的明文密码,只有哈希值。
因此,小偷将无法尝试在另一个系统中使用这些相同的密码(由于许多用户在任何地方都使用相同的密码,因此这很危险)。
```Python hl_lines="80-83"
{!../../../docs_src/security/tutorial003.py!}
```
#### 关于 `**user_dict`
`UserInDB(**user_dict)` 表示:
*直接将 `user_dict` 的键和值作为关键字参数传递,等同于:*
```Python
UserInDB(
username = user_dict["username"],
email = user_dict["email"],
full_name = user_dict["full_name"],
disabled = user_dict["disabled"],
hashed_password = user_dict["hashed_password"],
)
```
!!! info
有关 `user_dict` 的更完整说明,请参阅[**额外的模型**文档](../extra-models.md#about-user_indict){.internal-link target=_blank}。
## 返回令牌
`token` 端点的响应必须是一个 JSON 对象。
它应该有一个 `token_type`。在我们的例子中由于我们使用的是「Bearer」令牌因此令牌类型应为「`bearer`」。
并且还应该有一个 `access_token` 字段,它是一个包含我们的访问令牌的字符串。
对于这个简单的示例,我们将极其不安全地返回相同的 `username` 作为令牌。
!!! tip
在下一章中,你将看到一个真实的安全实现,使用了哈希密码和 <abbr title="JSON Web Tokens">JWT</abbr> 令牌。
但现在,让我们仅关注我们需要的特定细节。
```Python hl_lines="85"
{!../../../docs_src/security/tutorial003.py!}
```
!!! tip
根据规范,你应该像本示例一样,返回一个带有 `access_token` 和 `token_type` 的 JSON。
这是你必须在代码中自行完成的工作,并且要确保使用了这些 JSON 字段。
这几乎是唯一的你需要自己记住并正确地执行以符合规范的事情。
其余的,**FastAPI** 都会为你处理。
## 更新依赖项
现在我们将更新我们的依赖项。
我们想要仅当此用户处于启用状态时才能获取 `current_user`。
因此,我们创建了一个额外的依赖项 `get_current_active_user`,而该依赖项又以 `get_current_user` 作为依赖项。
如果用户不存在或处于未启用状态,则这两个依赖项都将仅返回 HTTP 错误。
因此,在我们的端点中,只有当用户存在,身份认证通过且处于启用状态时,我们才能获得该用户:
```Python hl_lines="58-67 69-72 90"
{!../../../docs_src/security/tutorial003.py!}
```
!!! info
我们在此处返回的值为 `Bearer` 的额外响应头 `WWW-Authenticate` 也是规范的一部分。
任何的 401「未认证」HTTP错误状态码都应该返回 `WWW-Authenticate` 响应头。
对于 bearer 令牌(我们的例子),该响应头的值应为 `Bearer`。
实际上你可以忽略这个额外的响应头,不会有什么问题。
但此处提供了它以符合规范。
而且,(现在或将来)可能会有工具期望得到并使用它,然后对你或你的用户有用处。
这就是遵循标准的好处...
## 实际效果
打开交互式文档:<a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>。
### 身份认证
点击「Authorize」按钮。
使用以下凭证:
用户名:`johndoe`
密码:`secret`
<img src="https://fastapi.tiangolo.com/img/tutorial/security/image04.png">
在系统中进行身份认证后,你将看到:
<img src="https://fastapi.tiangolo.com/img/tutorial/security/image05.png">
### 获取本人的用户数据
现在执行 `/users/me` 路径的 `GET` 操作。
你将获得你的用户数据,如:
```JSON
{
"username": "johndoe",
"email": "johndoe@example.com",
"full_name": "John Doe",
"disabled": false,
"hashed_password": "fakehashedsecret"
}
```
<img src="https://fastapi.tiangolo.com/img/tutorial/security/image06.png">
如果你点击锁定图标并注销,然后再次尝试同一操作,则会得到 HTTP 401 错误:
```JSON
{
"detail": "Not authenticated"
}
```
### 未启用的用户
现在尝试使用未启用的用户,并通过以下方式进行身份认证:
用户名:`alice`
密码:`secret2`
然后尝试执行 `/users/me` 路径的 `GET` 操作。
你将得到一个「未启用的用户」错误,如:
```JSON
{
"detail": "Inactive user"
}
```
## 总结
现在你掌握了为你的 API 实现一个基于 `username` 和 `password` 的完整安全系统的工具。
使用这些工具,你可以使安全系统与任何数据库以及任何用户或数据模型兼容。
唯一缺少的细节是它实际上还并不「安全」。
在下一章中,你将看到如何使用一个安全的哈希密码库和 <abbr title="JSON Web Tokens">JWT</abbr> 令牌。

View File

@@ -44,6 +44,7 @@ nav:
- it: /it/
- ja: /ja/
- ko: /ko/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
@@ -62,11 +63,24 @@ nav:
- tutorial/path-params-numeric-validations.md
- tutorial/body-multiple-params.md
- tutorial/body-fields.md
- tutorial/middleware.md
- tutorial/body-nested-models.md
- tutorial/header-params.md
- tutorial/response-model.md
- tutorial/extra-models.md
- tutorial/response-status-code.md
- tutorial/schema-extra-example.md
- tutorial/extra-data-types.md
- tutorial/cookie-params.md
- 安全性:
- tutorial/security/index.md
- tutorial/security/get-current-user.md
- tutorial/security/simple-oauth2.md
- tutorial/security/oauth2-jwt.md
- tutorial/cors.md
- tutorial/bigger-applications.md
- tutorial/metadata.md
- tutorial/debugging.md
- 高级用户指南:
- advanced/index.md
- advanced/path-operation-advanced-configuration.md
@@ -96,7 +110,9 @@ markdown_extensions:
extra:
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/typer
link: https://github.com/tiangolo/fastapi
- icon: fontawesome/brands/discord
link: https://discord.gg/VQjSZaeJmf
- icon: fontawesome/brands/twitter
link: https://twitter.com/tiangolo
- icon: fontawesome/brands/linkedin
@@ -120,6 +136,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /pl/
name: pl
- link: /pt/
name: pt - português
- link: /ru/

View File

@@ -0,0 +1,52 @@
from typing import Optional
from fastapi import Body, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
@app.put("/items/{item_id}")
async def update_item(
*,
item_id: int,
item: Item = Body(
...,
examples={
"normal": {
"summary": "A normal example",
"description": "A **normal** item works correctly.",
"value": {
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
},
},
"converted": {
"summary": "An example with converted data",
"description": "FastAPI can convert price `strings` to actual `numbers` automatically",
"value": {
"name": "Bar",
"price": "35.4",
},
},
"invalid": {
"summary": "Invalid data is rejected with an error",
"value": {
"name": "Baz",
"price": "thirty five point four",
},
},
},
),
):
results = {"item_id": item_id, "item": item}
return results

View File

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

View File

@@ -752,7 +752,7 @@ def get_body_field(*, dependant: Dependant, name: str) -> Optional[ModelField]:
for param in flat_dependant.body_params:
setattr(param.field_info, "embed", True)
model_name = "Body_" + name
BodyModel = create_model(model_name)
BodyModel: Type[BaseModel] = create_model(model_name)
for f in flat_dependant.body_params:
BodyModel.__fields__[f.name] = get_schema_compatible_field(field=f)
required = any(True for f in flat_dependant.body_params if f.required)

View File

@@ -1,6 +1,6 @@
from typing import Any, Dict, Optional, Sequence
from typing import Any, Dict, Optional, Sequence, Type
from pydantic import ValidationError, create_model
from pydantic import BaseModel, ValidationError, create_model
from pydantic.error_wrappers import ErrorList
from starlette.exceptions import HTTPException as StarletteHTTPException
@@ -16,8 +16,8 @@ class HTTPException(StarletteHTTPException):
self.headers = headers
RequestErrorModel = create_model("Request")
WebSocketErrorModel = create_model("WebSocket")
RequestErrorModel: Type[BaseModel] = create_model("Request")
WebSocketErrorModel: Type[BaseModel] = create_model("WebSocket")
class FastAPIError(RuntimeError):

View File

@@ -21,7 +21,7 @@ from fastapi.utils import (
get_model_definitions,
)
from pydantic import BaseModel
from pydantic.fields import ModelField
from pydantic.fields import ModelField, Undefined
from pydantic.schema import (
field_schema,
get_flat_models_from_fields,
@@ -101,6 +101,10 @@ def get_openapi_operation_parameters(
}
if field_info.description:
parameter["description"] = field_info.description
if field_info.examples:
parameter["examples"] = jsonable_encoder(field_info.examples)
elif field_info.example != Undefined:
parameter["example"] = jsonable_encoder(field_info.example)
if field_info.deprecated:
parameter["deprecated"] = field_info.deprecated
parameters.append(parameter)
@@ -124,7 +128,12 @@ def get_openapi_operation_request_body(
request_body_oai: Dict[str, Any] = {}
if required:
request_body_oai["required"] = required
request_body_oai["content"] = {request_media_type: {"schema": body_schema}}
request_media_content: Dict[str, Any] = {"schema": body_schema}
if field_info.examples:
request_media_content["examples"] = jsonable_encoder(field_info.examples)
elif field_info.example != Undefined:
request_media_content["example"] = jsonable_encoder(field_info.example)
request_body_oai["content"] = {request_media_type: request_media_content}
return request_body_oai

View File

@@ -1,6 +1,7 @@
from typing import Any, Callable, Optional, Sequence
from typing import Any, Callable, Dict, Optional, Sequence
from fastapi import params
from pydantic.fields import Undefined
def Path( # noqa: N802
@@ -16,6 +17,8 @@ def Path( # noqa: N802
min_length: Optional[int] = None,
max_length: Optional[int] = None,
regex: Optional[str] = None,
example: Any = Undefined,
examples: Optional[Dict[str, Any]] = None,
deprecated: Optional[bool] = None,
**extra: Any,
) -> Any:
@@ -31,6 +34,8 @@ def Path( # noqa: N802
min_length=min_length,
max_length=max_length,
regex=regex,
example=example,
examples=examples,
deprecated=deprecated,
**extra,
)
@@ -49,6 +54,8 @@ def Query( # noqa: N802
min_length: Optional[int] = None,
max_length: Optional[int] = None,
regex: Optional[str] = None,
example: Any = Undefined,
examples: Optional[Dict[str, Any]] = None,
deprecated: Optional[bool] = None,
**extra: Any,
) -> Any:
@@ -64,6 +71,8 @@ def Query( # noqa: N802
min_length=min_length,
max_length=max_length,
regex=regex,
example=example,
examples=examples,
deprecated=deprecated,
**extra,
)
@@ -83,6 +92,8 @@ def Header( # noqa: N802
min_length: Optional[int] = None,
max_length: Optional[int] = None,
regex: Optional[str] = None,
example: Any = Undefined,
examples: Optional[Dict[str, Any]] = None,
deprecated: Optional[bool] = None,
**extra: Any,
) -> Any:
@@ -99,6 +110,8 @@ def Header( # noqa: N802
min_length=min_length,
max_length=max_length,
regex=regex,
example=example,
examples=examples,
deprecated=deprecated,
**extra,
)
@@ -117,6 +130,8 @@ def Cookie( # noqa: N802
min_length: Optional[int] = None,
max_length: Optional[int] = None,
regex: Optional[str] = None,
example: Any = Undefined,
examples: Optional[Dict[str, Any]] = None,
deprecated: Optional[bool] = None,
**extra: Any,
) -> Any:
@@ -132,6 +147,8 @@ def Cookie( # noqa: N802
min_length=min_length,
max_length=max_length,
regex=regex,
example=example,
examples=examples,
deprecated=deprecated,
**extra,
)
@@ -152,6 +169,8 @@ def Body( # noqa: N802
min_length: Optional[int] = None,
max_length: Optional[int] = None,
regex: Optional[str] = None,
example: Any = Undefined,
examples: Optional[Dict[str, Any]] = None,
**extra: Any,
) -> Any:
return params.Body(
@@ -168,6 +187,8 @@ def Body( # noqa: N802
min_length=min_length,
max_length=max_length,
regex=regex,
example=example,
examples=examples,
**extra,
)
@@ -186,6 +207,8 @@ def Form( # noqa: N802
min_length: Optional[int] = None,
max_length: Optional[int] = None,
regex: Optional[str] = None,
example: Any = Undefined,
examples: Optional[Dict[str, Any]] = None,
**extra: Any,
) -> Any:
return params.Form(
@@ -201,6 +224,8 @@ def Form( # noqa: N802
min_length=min_length,
max_length=max_length,
regex=regex,
example=example,
examples=examples,
**extra,
)
@@ -219,6 +244,8 @@ def File( # noqa: N802
min_length: Optional[int] = None,
max_length: Optional[int] = None,
regex: Optional[str] = None,
example: Any = Undefined,
examples: Optional[Dict[str, Any]] = None,
**extra: Any,
) -> Any:
return params.File(
@@ -234,6 +261,8 @@ def File( # noqa: N802
min_length=min_length,
max_length=max_length,
regex=regex,
example=example,
examples=examples,
**extra,
)

View File

@@ -1,7 +1,7 @@
from enum import Enum
from typing import Any, Callable, Optional, Sequence
from typing import Any, Callable, Dict, Optional, Sequence
from pydantic.fields import FieldInfo
from pydantic.fields import FieldInfo, Undefined
class ParamTypes(Enum):
@@ -28,10 +28,14 @@ class Param(FieldInfo):
min_length: Optional[int] = None,
max_length: Optional[int] = None,
regex: Optional[str] = None,
example: Any = Undefined,
examples: Optional[Dict[str, Any]] = None,
deprecated: Optional[bool] = None,
**extra: Any,
):
self.deprecated = deprecated
self.example = example
self.examples = examples
super().__init__(
default,
alias=alias,
@@ -68,6 +72,8 @@ class Path(Param):
min_length: Optional[int] = None,
max_length: Optional[int] = None,
regex: Optional[str] = None,
example: Any = Undefined,
examples: Optional[Dict[str, Any]] = None,
deprecated: Optional[bool] = None,
**extra: Any,
):
@@ -85,6 +91,8 @@ class Path(Param):
max_length=max_length,
regex=regex,
deprecated=deprecated,
example=example,
examples=examples,
**extra,
)
@@ -106,6 +114,8 @@ class Query(Param):
min_length: Optional[int] = None,
max_length: Optional[int] = None,
regex: Optional[str] = None,
example: Any = Undefined,
examples: Optional[Dict[str, Any]] = None,
deprecated: Optional[bool] = None,
**extra: Any,
):
@@ -122,6 +132,8 @@ class Query(Param):
max_length=max_length,
regex=regex,
deprecated=deprecated,
example=example,
examples=examples,
**extra,
)
@@ -144,6 +156,8 @@ class Header(Param):
min_length: Optional[int] = None,
max_length: Optional[int] = None,
regex: Optional[str] = None,
example: Any = Undefined,
examples: Optional[Dict[str, Any]] = None,
deprecated: Optional[bool] = None,
**extra: Any,
):
@@ -161,6 +175,8 @@ class Header(Param):
max_length=max_length,
regex=regex,
deprecated=deprecated,
example=example,
examples=examples,
**extra,
)
@@ -182,6 +198,8 @@ class Cookie(Param):
min_length: Optional[int] = None,
max_length: Optional[int] = None,
regex: Optional[str] = None,
example: Any = Undefined,
examples: Optional[Dict[str, Any]] = None,
deprecated: Optional[bool] = None,
**extra: Any,
):
@@ -198,6 +216,8 @@ class Cookie(Param):
max_length=max_length,
regex=regex,
deprecated=deprecated,
example=example,
examples=examples,
**extra,
)
@@ -219,10 +239,14 @@ class Body(FieldInfo):
min_length: Optional[int] = None,
max_length: Optional[int] = None,
regex: Optional[str] = None,
example: Any = Undefined,
examples: Optional[Dict[str, Any]] = None,
**extra: Any,
):
self.embed = embed
self.media_type = media_type
self.example = example
self.examples = examples
super().__init__(
default,
alias=alias,
@@ -258,6 +282,8 @@ class Form(Body):
min_length: Optional[int] = None,
max_length: Optional[int] = None,
regex: Optional[str] = None,
example: Any = Undefined,
examples: Optional[Dict[str, Any]] = None,
**extra: Any,
):
super().__init__(
@@ -274,6 +300,8 @@ class Form(Body):
min_length=min_length,
max_length=max_length,
regex=regex,
example=example,
examples=examples,
**extra,
)
@@ -294,6 +322,8 @@ class File(Form):
min_length: Optional[int] = None,
max_length: Optional[int] = None,
regex: Optional[str] = None,
example: Any = Undefined,
examples: Optional[Dict[str, Any]] = None,
**extra: Any,
):
super().__init__(
@@ -309,6 +339,8 @@ class File(Form):
min_length=min_length,
max_length=max_length,
regex=regex,
example=example,
examples=examples,
**extra,
)

View File

@@ -7,7 +7,12 @@ from starlette.responses import PlainTextResponse as PlainTextResponse # noqa
from starlette.responses import RedirectResponse as RedirectResponse # noqa
from starlette.responses import Response as Response # noqa
from starlette.responses import StreamingResponse as StreamingResponse # noqa
from starlette.responses import UJSONResponse as UJSONResponse # noqa
try:
import ujson
except ImportError: # pragma: nocover
ujson = None # type: ignore
try:
import orjson
@@ -15,6 +20,12 @@ except ImportError: # pragma: nocover
orjson = None # type: ignore
class UJSONResponse(JSONResponse):
def render(self, content: Any) -> bytes:
assert ujson is not None, "ujson must be installed to use UJSONResponse"
return ujson.dumps(content, ensure_ascii=False).encode("utf-8")
class ORJSONResponse(JSONResponse):
media_type = "application/json"

View File

@@ -32,7 +32,7 @@ classifiers = [
"Topic :: Internet :: WWW/HTTP",
]
requires = [
"starlette ==0.13.6",
"starlette ==0.14.2",
"pydantic >=1.0.0,<2.0.0"
]
description-file = "README.md"
@@ -46,17 +46,18 @@ test = [
"pytest ==5.4.3",
"pytest-cov ==2.10.0",
"pytest-asyncio >=0.14.0,<0.15.0",
"mypy ==0.790",
"mypy ==0.812",
"flake8 >=3.8.3,<4.0.0",
"black ==20.8b1",
"isort >=5.0.6,<6.0.0",
"requests >=2.24.0,<3.0.0",
"httpx >=0.14.0,<0.15.0",
"email_validator >=1.1.1,<2.0.0",
"sqlalchemy >=1.3.18,<2.0.0",
"sqlalchemy >=1.3.18,<1.4.0",
"peewee >=3.13.3,<4.0.0",
"databases[sqlite] >=0.3.2,<0.4.0",
"orjson >=3.2.1,<4.0.0",
"ujson >=4.0.1,<5.0.0",
"async_exit_stack >=1.0.1,<2.0.0",
"async_generator >=1.10,<2.0.0",
"python-multipart >=0.0.5,<0.0.6",
@@ -87,7 +88,7 @@ all = [
"itsdangerous >=1.1.0,<2.0.0",
"pyyaml >=5.3.1,<6.0.0",
"graphene >=2.1.8,<3.0.0",
"ujson >=3.0.0,<4.0.0",
"ujson >=4.0.1,<5.0.0",
"orjson >=3.2.1,<4.0.0",
"email_validator >=1.1.1,<2.0.0",
"uvicorn[standard] >=0.12.0,<0.14.0",

View File

@@ -106,6 +106,9 @@ def new_lang(lang: str = typer.Argument(..., callback=lang_callback)):
en_index_content = en_index_path.read_text(encoding="utf-8")
new_index_content = f"{missing_translation_snippet}\n\n{en_index_content}"
new_index_path.write_text(new_index_content, encoding="utf-8")
new_overrides_gitignore_path = new_path / "overrides" / ".gitignore"
new_overrides_gitignore_path.parent.mkdir(parents=True, exist_ok=True)
new_overrides_gitignore_path.write_text("")
typer.secho(f"Successfully initialized: {new_path}", color=typer.colors.GREEN)
update_languages(lang=None)
@@ -206,6 +209,9 @@ index_sponsors_template = """
{% if sponsors %}
{% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
{% endfor -%}
{%- for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
{% endfor %}
{% endif %}
"""

View File

@@ -0,0 +1,889 @@
from fastapi import Body, Cookie, FastAPI, Header, Path, Query
from fastapi.testclient import TestClient
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
data: str
class Config:
schema_extra = {"example": {"data": "Data in schema_extra"}}
@app.post("/schema_extra/")
def schema_extra(item: Item):
return item
@app.post("/example/")
def example(item: Item = Body(..., example={"data": "Data in Body example"})):
return item
@app.post("/examples/")
def examples(
item: Item = Body(
...,
examples={
"example1": {
"summary": "example1 summary",
"value": {"data": "Data in Body examples, example1"},
},
"example2": {"value": {"data": "Data in Body examples, example2"}},
},
)
):
return item
@app.post("/example_examples/")
def example_examples(
item: Item = Body(
...,
example={"data": "Overriden example"},
examples={
"example1": {"value": {"data": "examples example_examples 1"}},
"example2": {"value": {"data": "examples example_examples 2"}},
},
)
):
return item
# TODO: enable these tests once/if Form(embed=False) is supported
# TODO: In that case, define if File() should support example/examples too
# @app.post("/form_example")
# def form_example(firstname: str = Form(..., example="John")):
# return firstname
# @app.post("/form_examples")
# def form_examples(
# lastname: str = Form(
# ...,
# examples={
# "example1": {"summary": "last name summary", "value": "Doe"},
# "example2": {"value": "Doesn't"},
# },
# ),
# ):
# return lastname
# @app.post("/form_example_examples")
# def form_example_examples(
# lastname: str = Form(
# ...,
# example="Doe overriden",
# examples={
# "example1": {"summary": "last name summary", "value": "Doe"},
# "example2": {"value": "Doesn't"},
# },
# ),
# ):
# return lastname
@app.get("/path_example/{item_id}")
def path_example(
item_id: str = Path(
...,
example="item_1",
),
):
return item_id
@app.get("/path_examples/{item_id}")
def path_examples(
item_id: str = Path(
...,
examples={
"example1": {"summary": "item ID summary", "value": "item_1"},
"example2": {"value": "item_2"},
},
),
):
return item_id
@app.get("/path_example_examples/{item_id}")
def path_example_examples(
item_id: str = Path(
...,
example="item_overriden",
examples={
"example1": {"summary": "item ID summary", "value": "item_1"},
"example2": {"value": "item_2"},
},
),
):
return item_id
@app.get("/query_example/")
def query_example(
data: str = Query(
None,
example="query1",
),
):
return data
@app.get("/query_examples/")
def query_examples(
data: str = Query(
None,
examples={
"example1": {"summary": "Query example 1", "value": "query1"},
"example2": {"value": "query2"},
},
),
):
return data
@app.get("/query_example_examples/")
def query_example_examples(
data: str = Query(
None,
example="query_overriden",
examples={
"example1": {"summary": "Qeury example 1", "value": "query1"},
"example2": {"value": "query2"},
},
),
):
return data
@app.get("/header_example/")
def header_example(
data: str = Header(
None,
example="header1",
),
):
return data
@app.get("/header_examples/")
def header_examples(
data: str = Header(
None,
examples={
"example1": {"summary": "header example 1", "value": "header1"},
"example2": {"value": "header2"},
},
),
):
return data
@app.get("/header_example_examples/")
def header_example_examples(
data: str = Header(
None,
example="header_overriden",
examples={
"example1": {"summary": "Qeury example 1", "value": "header1"},
"example2": {"value": "header2"},
},
),
):
return data
@app.get("/cookie_example/")
def cookie_example(
data: str = Cookie(
None,
example="cookie1",
),
):
return data
@app.get("/cookie_examples/")
def cookie_examples(
data: str = Cookie(
None,
examples={
"example1": {"summary": "cookie example 1", "value": "cookie1"},
"example2": {"value": "cookie2"},
},
),
):
return data
@app.get("/cookie_example_examples/")
def cookie_example_examples(
data: str = Cookie(
None,
example="cookie_overriden",
examples={
"example1": {"summary": "Qeury example 1", "value": "cookie1"},
"example2": {"value": "cookie2"},
},
),
):
return data
client = TestClient(app)
openapi_schema = {
"openapi": "3.0.2",
"info": {"title": "FastAPI", "version": "0.1.0"},
"paths": {
"/schema_extra/": {
"post": {
"summary": "Schema Extra",
"operationId": "schema_extra_schema_extra__post",
"requestBody": {
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/Item"}
}
},
"required": True,
},
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
"/example/": {
"post": {
"summary": "Example",
"operationId": "example_example__post",
"requestBody": {
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/Item"},
"example": {"data": "Data in Body example"},
}
},
"required": True,
},
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
"/examples/": {
"post": {
"summary": "Examples",
"operationId": "examples_examples__post",
"requestBody": {
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/Item"},
"examples": {
"example1": {
"summary": "example1 summary",
"value": {
"data": "Data in Body examples, example1"
},
},
"example2": {
"value": {"data": "Data in Body examples, example2"}
},
},
}
},
"required": True,
},
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
"/example_examples/": {
"post": {
"summary": "Example Examples",
"operationId": "example_examples_example_examples__post",
"requestBody": {
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/Item"},
"examples": {
"example1": {
"value": {"data": "examples example_examples 1"}
},
"example2": {
"value": {"data": "examples example_examples 2"}
},
},
}
},
"required": True,
},
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
"/path_example/{item_id}": {
"get": {
"summary": "Path Example",
"operationId": "path_example_path_example__item_id__get",
"parameters": [
{
"required": True,
"schema": {"title": "Item Id", "type": "string"},
"example": "item_1",
"name": "item_id",
"in": "path",
}
],
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
"/path_examples/{item_id}": {
"get": {
"summary": "Path Examples",
"operationId": "path_examples_path_examples__item_id__get",
"parameters": [
{
"required": True,
"schema": {"title": "Item Id", "type": "string"},
"examples": {
"example1": {
"summary": "item ID summary",
"value": "item_1",
},
"example2": {"value": "item_2"},
},
"name": "item_id",
"in": "path",
}
],
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
"/path_example_examples/{item_id}": {
"get": {
"summary": "Path Example Examples",
"operationId": "path_example_examples_path_example_examples__item_id__get",
"parameters": [
{
"required": True,
"schema": {"title": "Item Id", "type": "string"},
"examples": {
"example1": {
"summary": "item ID summary",
"value": "item_1",
},
"example2": {"value": "item_2"},
},
"name": "item_id",
"in": "path",
}
],
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
"/query_example/": {
"get": {
"summary": "Query Example",
"operationId": "query_example_query_example__get",
"parameters": [
{
"required": False,
"schema": {"title": "Data", "type": "string"},
"example": "query1",
"name": "data",
"in": "query",
}
],
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
"/query_examples/": {
"get": {
"summary": "Query Examples",
"operationId": "query_examples_query_examples__get",
"parameters": [
{
"required": False,
"schema": {"title": "Data", "type": "string"},
"examples": {
"example1": {
"summary": "Query example 1",
"value": "query1",
},
"example2": {"value": "query2"},
},
"name": "data",
"in": "query",
}
],
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
"/query_example_examples/": {
"get": {
"summary": "Query Example Examples",
"operationId": "query_example_examples_query_example_examples__get",
"parameters": [
{
"required": False,
"schema": {"title": "Data", "type": "string"},
"examples": {
"example1": {
"summary": "Qeury example 1",
"value": "query1",
},
"example2": {"value": "query2"},
},
"name": "data",
"in": "query",
}
],
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
"/header_example/": {
"get": {
"summary": "Header Example",
"operationId": "header_example_header_example__get",
"parameters": [
{
"required": False,
"schema": {"title": "Data", "type": "string"},
"example": "header1",
"name": "data",
"in": "header",
}
],
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
"/header_examples/": {
"get": {
"summary": "Header Examples",
"operationId": "header_examples_header_examples__get",
"parameters": [
{
"required": False,
"schema": {"title": "Data", "type": "string"},
"examples": {
"example1": {
"summary": "header example 1",
"value": "header1",
},
"example2": {"value": "header2"},
},
"name": "data",
"in": "header",
}
],
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
"/header_example_examples/": {
"get": {
"summary": "Header Example Examples",
"operationId": "header_example_examples_header_example_examples__get",
"parameters": [
{
"required": False,
"schema": {"title": "Data", "type": "string"},
"examples": {
"example1": {
"summary": "Qeury example 1",
"value": "header1",
},
"example2": {"value": "header2"},
},
"name": "data",
"in": "header",
}
],
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
"/cookie_example/": {
"get": {
"summary": "Cookie Example",
"operationId": "cookie_example_cookie_example__get",
"parameters": [
{
"required": False,
"schema": {"title": "Data", "type": "string"},
"example": "cookie1",
"name": "data",
"in": "cookie",
}
],
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
"/cookie_examples/": {
"get": {
"summary": "Cookie Examples",
"operationId": "cookie_examples_cookie_examples__get",
"parameters": [
{
"required": False,
"schema": {"title": "Data", "type": "string"},
"examples": {
"example1": {
"summary": "cookie example 1",
"value": "cookie1",
},
"example2": {"value": "cookie2"},
},
"name": "data",
"in": "cookie",
}
],
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
"/cookie_example_examples/": {
"get": {
"summary": "Cookie Example Examples",
"operationId": "cookie_example_examples_cookie_example_examples__get",
"parameters": [
{
"required": False,
"schema": {"title": "Data", "type": "string"},
"examples": {
"example1": {
"summary": "Qeury example 1",
"value": "cookie1",
},
"example2": {"value": "cookie2"},
},
"name": "data",
"in": "cookie",
}
],
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
},
},
"components": {
"schemas": {
"HTTPValidationError": {
"title": "HTTPValidationError",
"type": "object",
"properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {"$ref": "#/components/schemas/ValidationError"},
}
},
},
"Item": {
"title": "Item",
"required": ["data"],
"type": "object",
"properties": {"data": {"title": "Data", "type": "string"}},
"example": {"data": "Data in schema_extra"},
},
"ValidationError": {
"title": "ValidationError",
"required": ["loc", "msg", "type"],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
},
},
}
},
}
def test_openapi_schema():
"""
Test that example overrides work:
* pydantic model schema_extra is included
* Body(example={}) overrides schema_extra in pydantic model
* Body(examples{}) overrides Body(example={}) and schema_extra in pydantic model
"""
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json() == openapi_schema
def test_call_api():
response = client.post("/schema_extra/", json={"data": "Foo"})
assert response.status_code == 200, response.text
response = client.post("/example/", json={"data": "Foo"})
assert response.status_code == 200, response.text
response = client.post("/examples/", json={"data": "Foo"})
assert response.status_code == 200, response.text
response = client.post("/example_examples/", json={"data": "Foo"})
assert response.status_code == 200, response.text
response = client.get("/path_example/foo")
assert response.status_code == 200, response.text
response = client.get("/path_examples/foo")
assert response.status_code == 200, response.text
response = client.get("/path_example_examples/foo")
assert response.status_code == 200, response.text
response = client.get("/query_example/")
assert response.status_code == 200, response.text
response = client.get("/query_examples/")
assert response.status_code == 200, response.text
response = client.get("/query_example_examples/")
assert response.status_code == 200, response.text
response = client.get("/header_example/")
assert response.status_code == 200, response.text
response = client.get("/header_examples/")
assert response.status_code == 200, response.text
response = client.get("/header_example_examples/")
assert response.status_code == 200, response.text
response = client.get("/cookie_example/")
assert response.status_code == 200, response.text
response = client.get("/cookie_examples/")
assert response.status_code == 200, response.text
response = client.get("/cookie_example_examples/")
assert response.status_code == 200, response.text

View File

@@ -0,0 +1,36 @@
from fastapi.testclient import TestClient
from docs_src.custom_response.tutorial001 import app
client = TestClient(app)
openapi_schema = {
"openapi": "3.0.2",
"info": {"title": "FastAPI", "version": "0.1.0"},
"paths": {
"/items/": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
}
},
"summary": "Read Items",
"operationId": "read_items_items__get",
}
}
},
}
def test_openapi_schema():
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json() == openapi_schema
def test_get_custom_response():
response = client.get("/items/")
assert response.status_code == 200, response.text
assert response.json() == [{"item_id": "Foo"}]

View File

View File

@@ -0,0 +1,134 @@
from fastapi.testclient import TestClient
from docs_src.schema_extra_example.tutorial004 import app
client = TestClient(app)
openapi_schema = {
"openapi": "3.0.2",
"info": {"title": "FastAPI", "version": "0.1.0"},
"paths": {
"/items/{item_id}": {
"put": {
"summary": "Update Item",
"operationId": "update_item_items__item_id__put",
"parameters": [
{
"required": True,
"schema": {"title": "Item Id", "type": "integer"},
"name": "item_id",
"in": "path",
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/Item"},
"examples": {
"normal": {
"summary": "A normal example",
"description": "A **normal** item works correctly.",
"value": {
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
},
},
"converted": {
"summary": "An example with converted data",
"description": "FastAPI can convert price `strings` to actual `numbers` automatically",
"value": {"name": "Bar", "price": "35.4"},
},
"invalid": {
"summary": "Invalid data is rejected with an error",
"value": {
"name": "Baz",
"price": "thirty five point four",
},
},
},
}
},
"required": True,
},
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
},
},
},
}
}
},
"components": {
"schemas": {
"HTTPValidationError": {
"title": "HTTPValidationError",
"type": "object",
"properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {"$ref": "#/components/schemas/ValidationError"},
}
},
},
"Item": {
"title": "Item",
"required": ["name", "price"],
"type": "object",
"properties": {
"name": {"title": "Name", "type": "string"},
"description": {"title": "Description", "type": "string"},
"price": {"title": "Price", "type": "number"},
"tax": {"title": "Tax", "type": "number"},
},
},
"ValidationError": {
"title": "ValidationError",
"required": ["loc", "msg", "type"],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
},
},
}
},
}
def test_openapi_schema():
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json() == openapi_schema
# Test required and embedded body parameters with no bodies sent
def test_post_body_example():
response = client.put(
"/items/5",
json={
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
},
)
assert response.status_code == 200