mirror of
https://github.com/fastapi/fastapi.git
synced 2025-12-24 14:48:35 -05:00
Compare commits
73 Commits
typing-doc
...
0.103.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1bf5e7a10e | ||
|
|
fcda32d231 | ||
|
|
d0b17dd49c | ||
|
|
d769da3c38 | ||
|
|
2f50ae8825 | ||
|
|
831b5d5402 | ||
|
|
bc935e08b6 | ||
|
|
b944b55dfc | ||
|
|
74cf05117b | ||
|
|
1c4a9e91b6 | ||
|
|
b2f8ac6a83 | ||
|
|
99ffbcdee0 | ||
|
|
69f82e5222 | ||
|
|
27870e20f5 | ||
|
|
1453cea404 | ||
|
|
073e7fc950 | ||
|
|
0e2ca1cacb | ||
|
|
255e743f98 | ||
|
|
c89549c703 | ||
|
|
14e0914fcf | ||
|
|
3106a3a50e | ||
|
|
c75cdc6d9a | ||
|
|
cb410d3015 | ||
|
|
69a7c99b44 | ||
|
|
89246313aa | ||
|
|
79399e43df | ||
|
|
84794221d9 | ||
|
|
f4bc0d8205 | ||
|
|
2fcd8ce8ec | ||
|
|
46d1da08da | ||
|
|
571c7a7aba | ||
|
|
c6437d555d | ||
|
|
e0a99e24b8 | ||
|
|
a10c35673d | ||
|
|
766dfb5b38 | ||
|
|
bfde8f3ef2 | ||
|
|
ce8ee1410a | ||
|
|
118010ad5e | ||
|
|
8562cae44b | ||
|
|
e1a1a367a7 | ||
|
|
c502197d7c | ||
|
|
7f1dedac2c | ||
|
|
23511f1fdf | ||
|
|
7802454131 | ||
|
|
caf0b688cd | ||
|
|
a6d893fe98 | ||
|
|
1711c1e95f | ||
|
|
34028290f5 | ||
|
|
aa43afa4c0 | ||
|
|
0242ca7566 | ||
|
|
0ea23e2a8d | ||
|
|
7fe952f522 | ||
|
|
28bf4abf1f | ||
|
|
1866abffc1 | ||
|
|
e6c4785959 | ||
|
|
8979166bc3 | ||
|
|
2e32957198 | ||
|
|
b2562c5c73 | ||
|
|
a55f3204ef | ||
|
|
9fc33f8565 | ||
|
|
59cbeccac0 | ||
|
|
4e93f8e0bc | ||
|
|
ad76dd1aa8 | ||
|
|
48f6ccfe7d | ||
|
|
1d688a062e | ||
|
|
8cb33e9b47 | ||
|
|
d8f2f39f6d | ||
|
|
82ff9a6920 | ||
|
|
bf952d345c | ||
|
|
ee0b28a398 | ||
|
|
4bfe83bd27 | ||
|
|
7a63d11093 | ||
|
|
37d46e6b6c |
@@ -1,4 +1,4 @@
|
||||
FROM python:3.7
|
||||
FROM python:3.9
|
||||
|
||||
RUN pip install httpx "pydantic==1.5.1" pygithub
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM python:3.7
|
||||
FROM python:3.9
|
||||
|
||||
RUN pip install httpx PyGithub "pydantic==1.5.1" "pyyaml>=5.3.1,<6.0.0"
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import httpx
|
||||
from github import Github
|
||||
from pydantic import BaseModel, BaseSettings, SecretStr
|
||||
|
||||
awaiting_label = "awaiting review"
|
||||
awaiting_label = "awaiting-review"
|
||||
lang_all_label = "lang-all"
|
||||
approved_label = "approved-2"
|
||||
translations_path = Path(__file__).parent / "translations.yml"
|
||||
|
||||
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
id: cache
|
||||
with:
|
||||
path: ${{ env.pythonLocation }}
|
||||
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-pydantic-v2-${{ hashFiles('pyproject.toml', 'requirements-tests.txt') }}-test-v05
|
||||
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-pydantic-v2-${{ hashFiles('pyproject.toml', 'requirements-tests.txt') }}-test-v06
|
||||
- name: Install Dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install -r requirements-tests.txt
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
id: cache
|
||||
with:
|
||||
path: ${{ env.pythonLocation }}
|
||||
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ matrix.pydantic-version }}-${{ hashFiles('pyproject.toml', 'requirements-tests.txt') }}-test-v05
|
||||
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ matrix.pydantic-version }}-${{ hashFiles('pyproject.toml', 'requirements-tests.txt') }}-test-v06
|
||||
- name: Install Dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install -r requirements-tests.txt
|
||||
|
||||
@@ -50,14 +50,15 @@ The key features are:
|
||||
<a href="https://platform.sh/try-it-now/?utm_source=fastapi-signup&utm_medium=banner&utm_campaign=FastAPI-signup-June-2023" target="_blank" title="Build, run and scale your apps on a modern, reliable, and secure PaaS."><img src="https://fastapi.tiangolo.com/img/sponsors/platform-sh.png"></a>
|
||||
<a href="https://www.buildwithfern.com/?utm_source=tiangolo&utm_medium=website&utm_campaign=main-badge" target="_blank" title="Fern | SDKs and API docs"><img src="https://fastapi.tiangolo.com/img/sponsors/fern.svg"></a>
|
||||
<a href="https://www.porter.run" target="_blank" title="Deploy FastAPI on AWS with a few clicks"><img src="https://fastapi.tiangolo.com/img/sponsors/porter.png"></a>
|
||||
<a href="https://bump.sh/fastapi?utm_source=fastapi&utm_medium=referral&utm_campaign=sponsor" target="_blank" title="Automate FastAPI documentation generation with Bump.sh"><img src="https://fastapi.tiangolo.com/img/sponsors/bump-sh.png"></a>
|
||||
<a href="https://www.deta.sh/?ref=fastapi" target="_blank" title="The launchpad for all your (team's) ideas"><img src="https://fastapi.tiangolo.com/img/sponsors/deta.svg"></a>
|
||||
<a href="https://training.talkpython.fm/fastapi-courses" target="_blank" title="FastAPI video courses on demand from people you trust"><img src="https://fastapi.tiangolo.com/img/sponsors/talkpython.png"></a>
|
||||
<a href="https://testdriven.io/courses/tdd-fastapi/" target="_blank" title="Learn to build high-quality web apps with best practices"><img src="https://fastapi.tiangolo.com/img/sponsors/testdriven.svg"></a>
|
||||
<a href="https://github.com/deepset-ai/haystack/" target="_blank" title="Build powerful search from composable, open source building blocks"><img src="https://fastapi.tiangolo.com/img/sponsors/haystack-fastapi.svg"></a>
|
||||
<a href="https://careers.powens.com/" target="_blank" title="Powens is hiring!"><img src="https://fastapi.tiangolo.com/img/sponsors/powens.png"></a>
|
||||
<a href="https://www.svix.com/" target="_blank" title="Svix - Webhooks as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a>
|
||||
<a href="https://databento.com/" target="_blank" title="Pay as you go for market data"><img src="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a>
|
||||
<a href="https://speakeasyapi.dev?utm_source=fastapi+repo&utm_medium=github+sponsorship" target="_blank" title="SDKs for your API | Speakeasy"><img src="https://fastapi.tiangolo.com/img/sponsors/speakeasy.png"></a>
|
||||
<a href="https://www.svix.com/" target="_blank" title="Svix - Webhooks as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a>
|
||||
|
||||
<!-- /sponsors -->
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@ sponsors:
|
||||
- - login: cryptapi
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4
|
||||
url: https://github.com/cryptapi
|
||||
- login: porter-dev
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62078005?v=4
|
||||
url: https://github.com/porter-dev
|
||||
- login: fern-api
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/102944815?v=4
|
||||
url: https://github.com/fern-api
|
||||
@@ -17,24 +20,21 @@ sponsors:
|
||||
- - login: mikeckennedy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2035561?u=1bb18268bcd4d9249e1f783a063c27df9a84c05b&v=4
|
||||
url: https://github.com/mikeckennedy
|
||||
- login: ndimares
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6267663?u=cfb27efde7a7212be8142abb6c058a1aeadb41b1&v=4
|
||||
url: https://github.com/ndimares
|
||||
- login: deta
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/47275976?v=4
|
||||
url: https://github.com/deta
|
||||
- login: deepset-ai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/51827949?v=4
|
||||
url: https://github.com/deepset-ai
|
||||
- login: svix
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/80175132?v=4
|
||||
url: https://github.com/svix
|
||||
- login: databento-bot
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/98378480?u=494f679996e39427f7ddb1a7de8441b7c96fb670&v=4
|
||||
url: https://github.com/databento-bot
|
||||
- login: VincentParedes
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/103889729?v=4
|
||||
url: https://github.com/VincentParedes
|
||||
- - login: arcticfly
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41524992?u=03c88529a86cf51f7a380e890d84d84c71468848&v=4
|
||||
url: https://github.com/arcticfly
|
||||
- - login: getsentry
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1396951?v=4
|
||||
url: https://github.com/getsentry
|
||||
@@ -89,18 +89,18 @@ sponsors:
|
||||
- - login: povilasb
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1213442?u=b11f58ed6ceea6e8297c9b310030478ebdac894d&v=4
|
||||
url: https://github.com/povilasb
|
||||
- login: mukulmantosh
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/15572034?u=006f0a33c0e15bb2de57474a2cf7d2f8ee05f5a0&v=4
|
||||
url: https://github.com/mukulmantosh
|
||||
- login: primer-io
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4
|
||||
url: https://github.com/primer-io
|
||||
- - login: indeedeng
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2905043?v=4
|
||||
url: https://github.com/indeedeng
|
||||
- login: iguit0
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12905770?u=63a1a96d1e6c27d85c4f946b84836599de047f65&v=4
|
||||
url: https://github.com/iguit0
|
||||
- login: JacobKochems
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41692189?u=a75f62ddc0d060ee6233a91e19c433d2687b8eb6&v=4
|
||||
url: https://github.com/JacobKochems
|
||||
- login: NateXVI
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/48195620?u=4bc8751ae50cb087c40c1fe811764aa070b9eea6&v=4
|
||||
url: https://github.com/NateXVI
|
||||
- - login: Kludex
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
@@ -200,12 +200,12 @@ sponsors:
|
||||
- login: hiancdtrsnm
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7343177?v=4
|
||||
url: https://github.com/hiancdtrsnm
|
||||
- login: Shackelford-Arden
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7362263?v=4
|
||||
url: https://github.com/Shackelford-Arden
|
||||
- login: wdwinslow
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4
|
||||
url: https://github.com/wdwinslow
|
||||
- login: jsoques
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12414216?u=620921d94196546cc8b9eae2cc4cbc3f95bab42f&v=4
|
||||
url: https://github.com/jsoques
|
||||
- login: joeds13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13631604?u=628eb122e08bef43767b3738752b883e8e7f6259&v=4
|
||||
url: https://github.com/joeds13
|
||||
@@ -227,9 +227,6 @@ sponsors:
|
||||
- login: Filimoa
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/21352040?u=0be845711495bbd7b756e13fcaeb8efc1ebd78ba&v=4
|
||||
url: https://github.com/Filimoa
|
||||
- login: LarryGF
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26148349?u=431bb34d36d41c172466252242175281ae132152&v=4
|
||||
url: https://github.com/LarryGF
|
||||
- login: BrettskiPy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/30988215?u=d8a94a67e140d5ee5427724b292cc52d8827087a&v=4
|
||||
url: https://github.com/BrettskiPy
|
||||
@@ -239,6 +236,9 @@ sponsors:
|
||||
- login: Leay15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4
|
||||
url: https://github.com/Leay15
|
||||
- login: dvlpjrs
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32254642?u=fbd6ad0324d4f1eb6231cf775be1c7bd4404e961&v=4
|
||||
url: https://github.com/dvlpjrs
|
||||
- login: ygorpontelo
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32963605?u=35f7103f9c4c4c2589ae5737ee882e9375ef072e&v=4
|
||||
url: https://github.com/ygorpontelo
|
||||
@@ -284,15 +284,15 @@ sponsors:
|
||||
- login: DelfinaCare
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4
|
||||
url: https://github.com/DelfinaCare
|
||||
- login: hbakri
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/92298226?u=36eee6d75db1272264d3ee92f1871f70b8917bd8&v=4
|
||||
url: https://github.com/hbakri
|
||||
- login: osawa-koki
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/94336223?u=59c6fe6945bcbbaff87b2a794238671b060620d2&v=4
|
||||
url: https://github.com/osawa-koki
|
||||
- login: pyt3h
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/99658549?v=4
|
||||
url: https://github.com/pyt3h
|
||||
- login: Dagmaara
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/115501964?v=4
|
||||
url: https://github.com/Dagmaara
|
||||
- - login: SebTota
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25122511?v=4
|
||||
url: https://github.com/SebTota
|
||||
@@ -329,6 +329,9 @@ sponsors:
|
||||
- login: janfilips
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/870699?u=80702ec63f14e675cd4cdcc6ce3821d2ed207fd7&v=4
|
||||
url: https://github.com/janfilips
|
||||
- login: dodo5522
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1362607?u=9bf1e0e520cccc547c046610c468ce6115bbcf9f&v=4
|
||||
url: https://github.com/dodo5522
|
||||
- login: WillHogan
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=7036c064cf29781470573865264ec8e60b6b809f&v=4
|
||||
url: https://github.com/WillHogan
|
||||
@@ -374,9 +377,6 @@ sponsors:
|
||||
- login: katnoria
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7674948?u=09767eb13e07e09496c5fee4e5ce21d9eac34a56&v=4
|
||||
url: https://github.com/katnoria
|
||||
- login: mattwelke
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7719209?u=80f02a799323b1472b389b836d95957c93a6d856&v=4
|
||||
url: https://github.com/mattwelke
|
||||
- login: harsh183
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4
|
||||
url: https://github.com/harsh183
|
||||
@@ -422,6 +422,9 @@ sponsors:
|
||||
- login: jangia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/17927101?u=9261b9bb0c3e3bb1ecba43e8915dc58d8c9a077e&v=4
|
||||
url: https://github.com/jangia
|
||||
- login: timzaz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/19709244?u=e6658f6b0b188294ce2db20dad94a678fcea718d&v=4
|
||||
url: https://github.com/timzaz
|
||||
- login: shuheng-liu
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22414322?u=813c45f30786c6b511b21a661def025d8f7b609e&v=4
|
||||
url: https://github.com/shuheng-liu
|
||||
@@ -431,6 +434,9 @@ sponsors:
|
||||
- login: kxzk
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25046261?u=e185e58080090f9e678192cd214a14b14a2b232b&v=4
|
||||
url: https://github.com/kxzk
|
||||
- login: nisutec
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25281462?u=e562484c451fdfc59053163f64405f8eb262b8b0&v=4
|
||||
url: https://github.com/nisutec
|
||||
- login: hoenie-ams
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25708487?u=cda07434f0509ac728d9edf5e681117c0f6b818b&v=4
|
||||
url: https://github.com/hoenie-ams
|
||||
@@ -450,7 +456,7 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4
|
||||
url: https://github.com/engineerjoe440
|
||||
- login: bnkc
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=527044d90b5ebb7f8dad517db5da1f45253b774b&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=1a104991a2ea90bfe304bc0b9ef191c7e4891a0e&v=4
|
||||
url: https://github.com/bnkc
|
||||
- login: declon
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/36180226?v=4
|
||||
@@ -482,6 +488,15 @@ sponsors:
|
||||
- login: 0417taehyun
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4
|
||||
url: https://github.com/0417taehyun
|
||||
- login: romabozhanovgithub
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/67696229?u=e4b921eef096415300425aca249348f8abb78ad7&v=4
|
||||
url: https://github.com/romabozhanovgithub
|
||||
- login: mnicolleUTC
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/68548924?u=1fdd7f436bb1f4857c3415e62aa8fbc055fc1a76&v=4
|
||||
url: https://github.com/mnicolleUTC
|
||||
- login: mbukeRepo
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/70356088?u=e125069c6ac5c49355e2b3ca2aa66a445fc4cccd&v=4
|
||||
url: https://github.com/mbukeRepo
|
||||
- - login: ssbarnea
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/102495?u=b4bf6818deefe59952ac22fec6ed8c76de1b8f7c&v=4
|
||||
url: https://github.com/ssbarnea
|
||||
@@ -494,21 +509,18 @@ sponsors:
|
||||
- login: sadikkuzu
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=d179c06bb9f65c4167fcab118526819f8e0dac17&v=4
|
||||
url: https://github.com/sadikkuzu
|
||||
- login: ruizdiazever
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/29817086?u=2df54af55663d246e3a4dc8273711c37f1adb117&v=4
|
||||
url: https://github.com/ruizdiazever
|
||||
- login: samnimoh
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33413170?u=147bc516be6cb647b28d7e3b3fea3a018a331145&v=4
|
||||
url: https://github.com/samnimoh
|
||||
- login: danburonline
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34251194?u=2cad4388c1544e539ecb732d656e42fb07b4ff2d&v=4
|
||||
url: https://github.com/danburonline
|
||||
- login: iharshgor
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35490011?u=2dea054476e752d9e92c9d71a9a7cc919b1c2f8e&v=4
|
||||
url: https://github.com/iharshgor
|
||||
- login: koalawangyang
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/40114367?u=3bb94010f0473b8d4c2edea5a8c1cab61e6a1b22&v=4
|
||||
url: https://github.com/koalawangyang
|
||||
- login: rwxd
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4
|
||||
url: https://github.com/rwxd
|
||||
- login: ThomasPalma1
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/66331874?u=5763f7402d784ba189b60d704ff5849b4d0a63fb&v=4
|
||||
url: https://github.com/ThomasPalma1
|
||||
- login: lodine-software
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/133536046?v=4
|
||||
url: https://github.com/lodine-software
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
maintainers:
|
||||
- login: tiangolo
|
||||
answers: 1849
|
||||
prs: 466
|
||||
answers: 1866
|
||||
prs: 486
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=740f11212a731f56798f558ceddb0bd07642afa7&v=4
|
||||
url: https://github.com/tiangolo
|
||||
experts:
|
||||
- login: Kludex
|
||||
count: 463
|
||||
count: 480
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: dmontagu
|
||||
count: 239
|
||||
count: 240
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4
|
||||
url: https://github.com/dmontagu
|
||||
- login: Mause
|
||||
@@ -26,7 +26,7 @@ experts:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
|
||||
url: https://github.com/JarroVGIT
|
||||
- login: jgould22
|
||||
count: 157
|
||||
count: 164
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
|
||||
url: https://github.com/jgould22
|
||||
- login: euri10
|
||||
@@ -38,7 +38,7 @@ experts:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4
|
||||
url: https://github.com/phy25
|
||||
- login: iudeen
|
||||
count: 121
|
||||
count: 122
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
|
||||
url: https://github.com/iudeen
|
||||
- login: raphaelauv
|
||||
@@ -61,34 +61,34 @@ experts:
|
||||
count: 49
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4
|
||||
url: https://github.com/sm-Fifteen
|
||||
- login: insomnes
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
|
||||
url: https://github.com/insomnes
|
||||
- login: yinziyan1206
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4
|
||||
url: https://github.com/yinziyan1206
|
||||
- login: acidjunk
|
||||
- login: insomnes
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
|
||||
url: https://github.com/acidjunk
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
|
||||
url: https://github.com/insomnes
|
||||
- login: Dustyposa
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4
|
||||
url: https://github.com/Dustyposa
|
||||
- login: acidjunk
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
|
||||
url: https://github.com/acidjunk
|
||||
- login: adriangb
|
||||
count: 44
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=612704256e38d6ac9cbed24f10e4b6ac2da74ecb&v=4
|
||||
url: https://github.com/adriangb
|
||||
- login: frankie567
|
||||
count: 43
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4
|
||||
url: https://github.com/frankie567
|
||||
- login: odiseo0
|
||||
count: 43
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=241a71f6b7068738b81af3e57f45ffd723538401&v=4
|
||||
url: https://github.com/odiseo0
|
||||
- login: frankie567
|
||||
count: 43
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=c159fe047727aedecbbeeaa96a1b03ceb9d39add&v=4
|
||||
url: https://github.com/frankie567
|
||||
- login: includeamin
|
||||
count: 40
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4
|
||||
@@ -97,14 +97,14 @@ experts:
|
||||
count: 37
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4
|
||||
url: https://github.com/STeveShary
|
||||
- login: chbndrhnns
|
||||
count: 36
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
|
||||
url: https://github.com/chbndrhnns
|
||||
- login: krishnardt
|
||||
count: 35
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4
|
||||
url: https://github.com/krishnardt
|
||||
- login: chbndrhnns
|
||||
count: 35
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
|
||||
url: https://github.com/chbndrhnns
|
||||
- login: panla
|
||||
count: 32
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4
|
||||
@@ -117,26 +117,30 @@ experts:
|
||||
count: 26
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9bcce836bbce55835291c5b2ac93a4e311f4b3c3&v=4
|
||||
url: https://github.com/dbanty
|
||||
- login: n8sty
|
||||
count: 25
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4
|
||||
url: https://github.com/n8sty
|
||||
- login: wshayes
|
||||
count: 25
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
|
||||
url: https://github.com/wshayes
|
||||
- login: acnebs
|
||||
count: 23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9054108?v=4
|
||||
url: https://github.com/acnebs
|
||||
- login: SirTelemak
|
||||
count: 23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4
|
||||
url: https://github.com/SirTelemak
|
||||
- login: acnebs
|
||||
count: 23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9054108?v=4
|
||||
url: https://github.com/acnebs
|
||||
- login: rafsaf
|
||||
count: 21
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=5fe59a56e1f2f9ccd8005d71752a8276f133ae1a&v=4
|
||||
url: https://github.com/rafsaf
|
||||
- login: n8sty
|
||||
- login: JavierSanchezCastro
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4
|
||||
url: https://github.com/n8sty
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4
|
||||
url: https://github.com/JavierSanchezCastro
|
||||
- login: nsidnev
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22559461?u=a9cc3238217e21dc8796a1a500f01b722adb082c&v=4
|
||||
@@ -173,55 +177,51 @@ experts:
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4
|
||||
url: https://github.com/jonatasoli
|
||||
- login: ebottos94
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/100039558?u=e2c672da5a7977fd24d87ce6ab35f8bf5b1ed9fa&v=4
|
||||
url: https://github.com/ebottos94
|
||||
- login: dstlny
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4
|
||||
url: https://github.com/dstlny
|
||||
- login: abhint
|
||||
- login: chrisK824
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=b5d219277b4d001ac26fb8be357fddd88c29d51b&v=4
|
||||
url: https://github.com/abhint
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/79946379?u=03d85b22d696a58a9603e55fbbbe2de6b0f4face&v=4
|
||||
url: https://github.com/chrisK824
|
||||
- login: nymous
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4216559?u=360a36fb602cded27273cbfc0afc296eece90662&v=4
|
||||
url: https://github.com/nymous
|
||||
- login: ghost
|
||||
- login: abhint
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10137?u=b1951d34a583cf12ec0d3b0781ba19be97726318&v=4
|
||||
url: https://github.com/ghost
|
||||
- login: simondale00
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33907262?v=4
|
||||
url: https://github.com/simondale00
|
||||
- login: jorgerpo
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4
|
||||
url: https://github.com/jorgerpo
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=b5d219277b4d001ac26fb8be357fddd88c29d51b&v=4
|
||||
url: https://github.com/abhint
|
||||
last_month_active:
|
||||
- login: JavierSanchezCastro
|
||||
count: 12
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4
|
||||
url: https://github.com/JavierSanchezCastro
|
||||
- login: Kludex
|
||||
count: 24
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: jgould22
|
||||
count: 17
|
||||
count: 8
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
|
||||
url: https://github.com/jgould22
|
||||
- login: arjwilliams
|
||||
count: 8
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22227620?v=4
|
||||
url: https://github.com/arjwilliams
|
||||
- login: Ahmed-Abdou14
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/104530599?u=05365b155a1ff911532e8be316acfad2e0736f98&v=4
|
||||
url: https://github.com/Ahmed-Abdou14
|
||||
- login: iudeen
|
||||
- login: romabozhanovgithub
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/67696229?u=e4b921eef096415300425aca249348f8abb78ad7&v=4
|
||||
url: https://github.com/romabozhanovgithub
|
||||
- login: n8sty
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4
|
||||
url: https://github.com/n8sty
|
||||
- login: chrisK824
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
|
||||
url: https://github.com/iudeen
|
||||
- login: mikeedjones
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4087139?u=cc4a242896ac2fcf88a53acfaf190d0fe0a1f0c9&v=4
|
||||
url: https://github.com/mikeedjones
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/79946379?u=03d85b22d696a58a9603e55fbbbe2de6b0f4face&v=4
|
||||
url: https://github.com/chrisK824
|
||||
top_contributors:
|
||||
- login: waynerv
|
||||
count: 25
|
||||
@@ -235,22 +235,22 @@ top_contributors:
|
||||
count: 21
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: dmontagu
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4
|
||||
url: https://github.com/dmontagu
|
||||
- login: jaystone776
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4
|
||||
url: https://github.com/jaystone776
|
||||
- login: dmontagu
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4
|
||||
url: https://github.com/dmontagu
|
||||
- login: Xewus
|
||||
count: 14
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4
|
||||
url: https://github.com/Xewus
|
||||
- login: euri10
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
|
||||
url: https://github.com/euri10
|
||||
- login: Xewus
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4
|
||||
url: https://github.com/Xewus
|
||||
- login: mariacamilagl
|
||||
count: 12
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4
|
||||
@@ -360,6 +360,10 @@ top_reviewers:
|
||||
count: 78
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=d7062cbc6eb7671d5dc9cc0e32a24ae335e0f225&v=4
|
||||
url: https://github.com/yezz123
|
||||
- login: iudeen
|
||||
count: 53
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
|
||||
url: https://github.com/iudeen
|
||||
- login: tokusumi
|
||||
count: 51
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
|
||||
@@ -372,10 +376,6 @@ top_reviewers:
|
||||
count: 47
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/59285379?v=4
|
||||
url: https://github.com/Laineyzhang55
|
||||
- login: iudeen
|
||||
count: 46
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
|
||||
url: https://github.com/iudeen
|
||||
- login: ycd
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4
|
||||
@@ -385,7 +385,7 @@ top_reviewers:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24587499?u=e772190a051ab0eaa9c8542fcff1892471638f2b&v=4
|
||||
url: https://github.com/cikay
|
||||
- login: Xewus
|
||||
count: 38
|
||||
count: 39
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4
|
||||
url: https://github.com/Xewus
|
||||
- login: JarroVGIT
|
||||
@@ -482,7 +482,7 @@ top_reviewers:
|
||||
url: https://github.com/sh0nk
|
||||
- login: peidrao
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=5b94b548ef0002ef3219d7c07ac0fac17c6201a2&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=a66902b40c13647d0ed0e573d598128240a4dd04&v=4
|
||||
url: https://github.com/peidrao
|
||||
- login: r0b2g1t
|
||||
count: 13
|
||||
|
||||
@@ -11,6 +11,9 @@ gold:
|
||||
- url: https://www.porter.run
|
||||
title: Deploy FastAPI on AWS with a few clicks
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/porter.png
|
||||
- url: https://bump.sh/fastapi?utm_source=fastapi&utm_medium=referral&utm_campaign=sponsor
|
||||
title: Automate FastAPI documentation generation with Bump.sh
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/bump-sh.png
|
||||
silver:
|
||||
- url: https://www.deta.sh/?ref=fastapi
|
||||
title: The launchpad for all your (team's) ideas
|
||||
@@ -27,22 +30,19 @@ silver:
|
||||
- url: https://careers.powens.com/
|
||||
title: Powens is hiring!
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/powens.png
|
||||
- url: https://www.svix.com/
|
||||
title: Svix - Webhooks as a service
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/svix.svg
|
||||
- url: https://databento.com/
|
||||
title: Pay as you go for market data
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/databento.svg
|
||||
- url: https://speakeasyapi.dev?utm_source=fastapi+repo&utm_medium=github+sponsorship
|
||||
title: SDKs for your API | Speakeasy
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/speakeasy.png
|
||||
- url: https://www.svix.com/
|
||||
title: Svix - Webhooks as a service
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/svix.svg
|
||||
bronze:
|
||||
- url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source
|
||||
title: Biosecurity risk assessments made easy.
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/exoflare.png
|
||||
- url: https://www.flint.sh
|
||||
title: IT expertise, consulting and development by passionate people
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/flint.png
|
||||
- url: https://bit.ly/3JJ7y5C
|
||||
title: Build cross-modal and multimodal applications on the cloud
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/jina2.svg
|
||||
|
||||
@@ -12,7 +12,6 @@ logins:
|
||||
- ObliviousAI
|
||||
- Doist
|
||||
- nihpo
|
||||
- svix
|
||||
- armand-sauzay
|
||||
- databento-bot
|
||||
- nanram22
|
||||
@@ -20,3 +19,4 @@ logins:
|
||||
- porter-dev
|
||||
- fern-api
|
||||
- ndimares
|
||||
- svixhq
|
||||
|
||||
@@ -90,7 +90,9 @@ Let's see what each of those options mean:
|
||||
```
|
||||
|
||||
* So, the colon in `main:app` would be equivalent to the Python `import` part in `from main import app`.
|
||||
|
||||
* `--workers`: The number of worker processes to use, each will run a Uvicorn worker, in this case, 4 workers.
|
||||
|
||||
* `--worker-class`: The Gunicorn-compatible worker class to use in the worker processes.
|
||||
* Here we pass the class that Gunicorn can import and use with:
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ If you interact with the docs and check the response, even though the code didn'
|
||||
|
||||
This means that it will **always have a value**, it's just that sometimes the value could be `None` (or `null` in JSON).
|
||||
|
||||
That means that, clients using your API don't have to check if the value exists or not, they can **asume the field will always be there**, but just that in some cases it will have the default value of `None`.
|
||||
That means that, clients using your API don't have to check if the value exists or not, they can **assume the field will always be there**, but just that in some cases it will have the default value of `None`.
|
||||
|
||||
The way to describe this in OpenAPI, is to mark that field as **required**, because it will always be there.
|
||||
|
||||
|
||||
BIN
docs/en/docs/img/sponsors/bump-sh-banner.png
Executable file
BIN
docs/en/docs/img/sponsors/bump-sh-banner.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 9.9 KiB |
BIN
docs/en/docs/img/sponsors/bump-sh.png
Executable file
BIN
docs/en/docs/img/sponsors/bump-sh.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -2,6 +2,67 @@
|
||||
|
||||
## Latest Changes
|
||||
|
||||
## 0.103.2
|
||||
|
||||
### Refactors
|
||||
|
||||
* ⬆️ Upgrade compatibility with Pydantic v2.4, new renamed functions and JSON Schema input/output models with default values. PR [#10344](https://github.com/tiangolo/fastapi/pull/10344) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/extra-data-types.md`. PR [#10132](https://github.com/tiangolo/fastapi/pull/10132) by [@ArtemKhymenko](https://github.com/ArtemKhymenko).
|
||||
* 🌐 Fix typos in French translations for `docs/fr/docs/advanced/path-operation-advanced-configuration.md`, `docs/fr/docs/alternatives.md`, `docs/fr/docs/async.md`, `docs/fr/docs/features.md`, `docs/fr/docs/help-fastapi.md`, `docs/fr/docs/index.md`, `docs/fr/docs/python-types.md`, `docs/fr/docs/tutorial/body.md`, `docs/fr/docs/tutorial/first-steps.md`, `docs/fr/docs/tutorial/query-params.md`. PR [#10154](https://github.com/tiangolo/fastapi/pull/10154) by [@s-rigaud](https://github.com/s-rigaud).
|
||||
* 🌐 Add Chinese translation for `docs/zh/docs/async.md`. PR [#5591](https://github.com/tiangolo/fastapi/pull/5591) by [@mkdir700](https://github.com/mkdir700).
|
||||
* 🌐 Update Chinese translation for `docs/tutorial/security/simple-oauth2.md`. PR [#3844](https://github.com/tiangolo/fastapi/pull/3844) by [@jaystone776](https://github.com/jaystone776).
|
||||
* 🌐 Add Korean translation for `docs/ko/docs/deployment/cloud.md`. PR [#10191](https://github.com/tiangolo/fastapi/pull/10191) by [@Sion99](https://github.com/Sion99).
|
||||
* 🌐 Add Japanese translation for `docs/ja/docs/deployment/https.md`. PR [#10298](https://github.com/tiangolo/fastapi/pull/10298) by [@tamtam-fitness](https://github.com/tamtam-fitness).
|
||||
* 🌐 Fix typo in Russian translation for `docs/ru/docs/tutorial/body-fields.md`. PR [#10224](https://github.com/tiangolo/fastapi/pull/10224) by [@AlertRED](https://github.com/AlertRED).
|
||||
* 🌐 Add Polish translation for `docs/pl/docs/help-fastapi.md`. PR [#10121](https://github.com/tiangolo/fastapi/pull/10121) by [@romabozhanovgithub](https://github.com/romabozhanovgithub).
|
||||
* 🌐 Add Russian translation for `docs/ru/docs/tutorial/header-params.md`. PR [#10226](https://github.com/tiangolo/fastapi/pull/10226) by [@AlertRED](https://github.com/AlertRED).
|
||||
* 🌐 Add Chinese translation for `docs/zh/docs/deployment/versions.md`. PR [#10276](https://github.com/tiangolo/fastapi/pull/10276) by [@xzmeng](https://github.com/xzmeng).
|
||||
|
||||
### Internal
|
||||
|
||||
* 🔧 Update sponsors, remove Flint. PR [#10349](https://github.com/tiangolo/fastapi/pull/10349) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Rename label "awaiting review" to "awaiting-review" to simplify search queries. PR [#10343](https://github.com/tiangolo/fastapi/pull/10343) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Update sponsors, enable Svix (revert #10228). PR [#10253](https://github.com/tiangolo/fastapi/pull/10253) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Update sponsors, remove Svix. PR [#10228](https://github.com/tiangolo/fastapi/pull/10228) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Update sponsors, add Bump.sh. PR [#10227](https://github.com/tiangolo/fastapi/pull/10227) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.103.1
|
||||
|
||||
### Fixes
|
||||
|
||||
* 📌 Pin AnyIO to < 4.0.0 to handle an incompatibility while upgrading to Starlette 0.31.1. PR [#10194](https://github.com/tiangolo/fastapi/pull/10194) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Docs
|
||||
|
||||
* ✏️ Fix validation parameter name in docs, from `regex` to `pattern`. PR [#10085](https://github.com/tiangolo/fastapi/pull/10085) by [@pablodorrio](https://github.com/pablodorrio).
|
||||
* ✏️ Fix indent format in `docs/en/docs/deployment/server-workers.md`. PR [#10066](https://github.com/tiangolo/fastapi/pull/10066) by [@tamtam-fitness](https://github.com/tamtam-fitness).
|
||||
* ✏️ Fix Pydantic examples in tutorial for Python types. PR [#9961](https://github.com/tiangolo/fastapi/pull/9961) by [@rahulsalgare](https://github.com/rahulsalgare).
|
||||
* ✏️ Fix link to Pydantic docs in `docs/en/docs/tutorial/extra-data-types.md`. PR [#10155](https://github.com/tiangolo/fastapi/pull/10155) by [@hasnatsajid](https://github.com/hasnatsajid).
|
||||
* ✏️ Fix typo in `docs/en/docs/tutorial/handling-errors.md`. PR [#10170](https://github.com/tiangolo/fastapi/pull/10170) by [@poupapaa](https://github.com/poupapaa).
|
||||
* ✏️ Fix typo in `docs/en/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md`. PR [#10172](https://github.com/tiangolo/fastapi/pull/10172) by [@ragul-kachiappan](https://github.com/ragul-kachiappan).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Remove duplicate line in translation for `docs/pt/docs/tutorial/path-params.md`. PR [#10126](https://github.com/tiangolo/fastapi/pull/10126) by [@LecoOliveira](https://github.com/LecoOliveira).
|
||||
* 🌐 Add Yoruba translation for `docs/yo/docs/index.md`. PR [#10033](https://github.com/tiangolo/fastapi/pull/10033) by [@AfolabiOlaoluwa](https://github.com/AfolabiOlaoluwa).
|
||||
* 🌐 Add Ukrainian translation for `docs/uk/docs/python-types.md`. PR [#10080](https://github.com/tiangolo/fastapi/pull/10080) by [@rostik1410](https://github.com/rostik1410).
|
||||
* 🌐 Add Vietnamese translations for `docs/vi/docs/tutorial/first-steps.md` and `docs/vi/docs/tutorial/index.md`. PR [#10088](https://github.com/tiangolo/fastapi/pull/10088) by [@magiskboy](https://github.com/magiskboy).
|
||||
* 🌐 Add Ukrainian translation for `docs/uk/docs/alternatives.md`. PR [#10060](https://github.com/tiangolo/fastapi/pull/10060) by [@whysage](https://github.com/whysage).
|
||||
* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/index.md`. PR [#10079](https://github.com/tiangolo/fastapi/pull/10079) by [@rostik1410](https://github.com/rostik1410).
|
||||
* ✏️ Fix typos in `docs/en/docs/how-to/separate-openapi-schemas.md` and `docs/en/docs/tutorial/schema-extra-example.md`. PR [#10189](https://github.com/tiangolo/fastapi/pull/10189) by [@xzmeng](https://github.com/xzmeng).
|
||||
* 🌐 Add Chinese translation for `docs/zh/docs/advanced/generate-clients.md`. PR [#9883](https://github.com/tiangolo/fastapi/pull/9883) by [@funny-cat-happy](https://github.com/funny-cat-happy).
|
||||
|
||||
### Refactors
|
||||
|
||||
* ✏️ Fix typos in comment in `fastapi/applications.py`. PR [#10045](https://github.com/tiangolo/fastapi/pull/10045) by [@AhsanSheraz](https://github.com/AhsanSheraz).
|
||||
* ✅ Add missing test for OpenAPI examples, it was missing in coverage. PR [#10188](https://github.com/tiangolo/fastapi/pull/10188) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Internal
|
||||
|
||||
* 👥 Update FastAPI People. PR [#10186](https://github.com/tiangolo/fastapi/pull/10186) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.103.0
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ It should be a `list` of `Depends()`:
|
||||
{!> ../../../docs_src/dependencies/tutorial006.py!}
|
||||
```
|
||||
|
||||
These dependencies will be executed/solved the same way normal dependencies. But their value (if they return any) won't be passed to your *path operation function*.
|
||||
These dependencies will be executed/solved the same way as normal dependencies. But their value (if they return any) won't be passed to your *path operation function*.
|
||||
|
||||
!!! tip
|
||||
Some editors check for unused function parameters, and show them as errors.
|
||||
|
||||
@@ -49,7 +49,7 @@ Here are some of the additional data types you can use:
|
||||
* `Decimal`:
|
||||
* Standard Python `Decimal`.
|
||||
* In requests and responses, handled the same as a `float`.
|
||||
* You can check all the valid pydantic data types here: <a href="https://pydantic-docs.helpmanual.io/usage/types" class="external-link" target="_blank">Pydantic data types</a>.
|
||||
* You can check all the valid pydantic data types here: <a href="https://docs.pydantic.dev/latest/usage/types/types/" class="external-link" target="_blank">Pydantic data types</a>.
|
||||
|
||||
## Example
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Handling Errors
|
||||
|
||||
There are many situations in where you need to notify an error to a client that is using your API.
|
||||
There are many situations in which you need to notify an error to a client that is using your API.
|
||||
|
||||
This client could be a browser with a frontend, a code from someone else, an IoT device, etc.
|
||||
|
||||
|
||||
@@ -932,7 +932,7 @@ Validations specific for strings:
|
||||
|
||||
* `min_length`
|
||||
* `max_length`
|
||||
* `regex`
|
||||
* `pattern`
|
||||
|
||||
In these examples you saw how to declare validations for `str` values.
|
||||
|
||||
|
||||
@@ -38,13 +38,13 @@ That extra info will be added as-is to the output **JSON Schema** for that model
|
||||
|
||||
In Pydantic version 2, you would use the attribute `model_config`, that takes a `dict` as described in <a href="https://docs.pydantic.dev/latest/usage/model_config/" class="external-link" target="_blank">Pydantic's docs: Model Config</a>.
|
||||
|
||||
You can set `"json_schema_extra"` with a `dict` containing any additonal data you would like to show up in the generated JSON Schema, including `examples`.
|
||||
You can set `"json_schema_extra"` with a `dict` containing any additional data you would like to show up in the generated JSON Schema, including `examples`.
|
||||
|
||||
=== "Pydantic v1"
|
||||
|
||||
In Pydantic version 1, you would use an internal class `Config` and `schema_extra`, as described in <a href="https://docs.pydantic.dev/1.10/usage/schema/#schema-customization" class="external-link" target="_blank">Pydantic's docs: Schema customization</a>.
|
||||
|
||||
You can set `schema_extra` with a `dict` containing any additonal data you would like to show up in the generated JSON Schema, including `examples`.
|
||||
You can set `schema_extra` with a `dict` containing any additional data you would like to show up in the generated JSON Schema, including `examples`.
|
||||
|
||||
!!! tip
|
||||
You could use the same technique to extend the JSON Schema and add your own custom extra info.
|
||||
|
||||
@@ -72,6 +72,7 @@ nav:
|
||||
- uk: /uk/
|
||||
- ur: /ur/
|
||||
- vi: /vi/
|
||||
- yo: /yo/
|
||||
- zh: /zh/
|
||||
- features.md
|
||||
- fastapi-people.md
|
||||
@@ -261,6 +262,8 @@ extra:
|
||||
name: ur
|
||||
- link: /vi/
|
||||
name: vi - Tiếng Việt
|
||||
- link: /yo/
|
||||
name: yo - Yorùbá
|
||||
- link: /zh/
|
||||
name: zh - 汉语
|
||||
extra_css:
|
||||
|
||||
@@ -46,6 +46,12 @@
|
||||
<img class="sponsor-image" src="/img/sponsors/porter-banner.png" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
<a title="Automate FastAPI documentation generation with Bump.sh" style="display: block; position: relative;" href="https://bump.sh/fastapi?utm_source=fastapi&utm_medium=referral&utm_campaign=sponsor" target="_blank">
|
||||
<span class="sponsor-badge">sponsor</span>
|
||||
<img class="sponsor-image" src="/img/sponsors/bump-sh-banner.png" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -66,7 +66,7 @@ Il y a un chapitre entier ici dans la documentation à ce sujet, vous pouvez le
|
||||
Lorsque vous déclarez un *chemin* dans votre application, **FastAPI** génère automatiquement les métadonnées concernant ce *chemin* à inclure dans le schéma OpenAPI.
|
||||
|
||||
!!! note "Détails techniques"
|
||||
La spécification OpenAPI appelle ces métaonnées des <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object" class="external-link" target="_blank">Objets d'opération</a>.
|
||||
La spécification OpenAPI appelle ces métadonnées des <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object" class="external-link" target="_blank">Objets d'opération</a>.
|
||||
|
||||
Il contient toutes les informations sur le *chemin* et est utilisé pour générer automatiquement la documentation.
|
||||
|
||||
|
||||
@@ -387,7 +387,7 @@ Gérer toute la validation des données, leur sérialisation et la documentation
|
||||
|
||||
### <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>
|
||||
|
||||
Starlette est un framework/toolkit léger <abbr title="Le nouveau standard pour construire des applications web assynchrones en Python">ASGI</abbr>, qui est idéal pour construire des services asyncio performants.
|
||||
Starlette est un framework/toolkit léger <abbr title="Le nouveau standard pour construire des applications web asynchrones en Python">ASGI</abbr>, qui est idéal pour construire des services asyncio performants.
|
||||
|
||||
Il est très simple et intuitif. Il est conçu pour être facilement extensible et avoir des composants modulaires.
|
||||
|
||||
|
||||
@@ -250,7 +250,7 @@ Par exemple :
|
||||
|
||||
### Concurrence + Parallélisme : Web + Machine Learning
|
||||
|
||||
Avec **FastAPI** vous pouvez bénéficier de la concurrence qui est très courante en developement web (c'est l'attrait principal de NodeJS).
|
||||
Avec **FastAPI** vous pouvez bénéficier de la concurrence qui est très courante en développement web (c'est l'attrait principal de NodeJS).
|
||||
|
||||
Mais vous pouvez aussi profiter du parallélisme et multiprocessing afin de gérer des charges **CPU bound** qui sont récurrentes dans les systèmes de *Machine Learning*.
|
||||
|
||||
|
||||
@@ -71,9 +71,9 @@ my_second_user: User = User(**second_user_data)
|
||||
|
||||
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>.
|
||||
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.
|
||||
Tout le framework **FastAPI** a été conçu avec cela en tête. L'autocomplétion fonctionne partout.
|
||||
|
||||
Vous devrez rarement revenir à la documentation.
|
||||
|
||||
@@ -136,7 +136,7 @@ FastAPI contient un système simple mais extrêmement puissant d'<abbr title='au
|
||||
|
||||
* 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.
|
||||
* Toutes les dépendances peuvent exiger 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.
|
||||
@@ -157,11 +157,11 @@ Tout intégration est conçue pour être si simple à utiliser (avec des dépend
|
||||
|
||||
**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.
|
||||
En fait, `FastAPI` est un sous composant 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>.
|
||||
* Des performances vraiment 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>
|
||||
@@ -180,7 +180,7 @@ Inclus des librairies externes basées, aussi, sur Pydantic, servent d'<abbr tit
|
||||
|
||||
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**
|
||||
Inversement, 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):
|
||||
|
||||
@@ -194,7 +194,7 @@ Avec **FastAPI** vous aurez toutes les fonctionnalités de **Pydantic** (comme
|
||||
* 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.
|
||||
* Vous pouvez avoir des objets **JSON fortement 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.
|
||||
|
||||
@@ -36,8 +36,8 @@ Vous pouvez :
|
||||
* <a href="https://twitter.com/tiangolo" class="external-link" target="_blank">Me suivre sur **Twitter**</a>.
|
||||
* Dites-moi comment vous utilisez FastAPI (j'adore entendre ça).
|
||||
* Entendre quand je fais des annonces ou que je lance de nouveaux outils.
|
||||
* <a href="https://www.linkedin.com/in/tiangolo/" class="external-link" target="_blank">Vous connectez à moi sur **Linkedin**</a>.
|
||||
* Etre notifié quand je fais des annonces ou que je lance de nouveaux outils (bien que j'utilise plus souvent Twitte 🤷♂).
|
||||
* <a href="https://www.linkedin.com/in/tiangolo/" class="external-link" target="_blank">Vous connectez à moi sur **LinkedIn**</a>.
|
||||
* Etre notifié quand je fais des annonces ou que je lance de nouveaux outils (bien que j'utilise plus souvent Twitter 🤷♂).
|
||||
* Lire ce que j’écris (ou me suivre) sur <a href="https://dev.to/tiangolo" class="external-link" target="_blank">**Dev.to**</a> ou <a href="https://medium.com/@tiangolo" class="external-link" target="_blank">**Medium**</a>.
|
||||
* Lire d'autres idées, articles, et sur les outils que j'ai créés.
|
||||
* Suivez-moi pour lire quand je publie quelque chose de nouveau.
|
||||
|
||||
@@ -424,7 +424,7 @@ Pour un exemple plus complet comprenant plus de fonctionnalités, voir le <a hre
|
||||
|
||||
* Déclaration de **paramètres** provenant d'autres endroits différents comme : **<abbr title="en anglais : headers">en-têtes</abbr>.**, **cookies**, **champs de formulaire** et **fichiers**.
|
||||
* L'utilisation de **contraintes de validation** comme `maximum_length` ou `regex`.
|
||||
* Un **<abbr title="aussi connu sous le nom de composants, ressources, fournisseurs, services, injectables">systéme d'injection de dépendance </abbr>** très puissant et facile à utiliser .
|
||||
* Un **<abbr title="aussi connu sous le nom de composants, ressources, fournisseurs, services, injectables">système d'injection de dépendance </abbr>** très puissant et facile à utiliser .
|
||||
* Sécurité et authentification, y compris la prise en charge de **OAuth2** avec les **<abbr title="en anglais : JWT tokens">jetons <abbr title="JSON Web Tokens">JWT</abbr></abbr>** et l'authentification **HTTP Basic**.
|
||||
* Des techniques plus avancées (mais tout aussi faciles) pour déclarer les **modèles <abbr title="JavaScript Object Notation">JSON</abbr> profondément imbriqués** (grâce à Pydantic).
|
||||
* Intégration de **GraphQL** avec <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> et d'autres bibliothèques.
|
||||
@@ -450,7 +450,7 @@ Utilisées par Pydantic:
|
||||
Utilisées par Starlette :
|
||||
|
||||
* <a href="https://requests.readthedocs.io" target="_blank"><code>requests</code></a> - Obligatoire si vous souhaitez utiliser `TestClient`.
|
||||
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Obligatoire si vous souhaitez utiliser la configuration de template par defaut.
|
||||
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Obligatoire si vous souhaitez utiliser la configuration de template par défaut.
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Obligatoire si vous souhaitez supporter le <abbr title="convertit la chaine de caractère d'une requête HTTP en donnée Python">"décodage"</abbr> de formulaire avec `request.form()`.
|
||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Obligatoire pour la prise en charge de `SessionMiddleware`.
|
||||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Obligatoire pour le support `SchemaGenerator` de Starlette (vous n'en avez probablement pas besoin avec FastAPI).
|
||||
|
||||
@@ -119,7 +119,7 @@ Comme l'éditeur connaît le type des variables, vous n'avez pas seulement l'aut
|
||||
|
||||
<img src="/img/python-types/image04.png">
|
||||
|
||||
Maintenant que vous avez connaissance du problème, convertissez `age` en <abbr title="string">chaine de caractères</abbr> grâce à `str(age)` :
|
||||
Maintenant que vous avez connaissance du problème, convertissez `age` en <abbr title="string">chaîne de caractères</abbr> grâce à `str(age)` :
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!../../../docs_src/python_types/tutorial004.py!}
|
||||
|
||||
@@ -98,7 +98,7 @@ Et vous obtenez aussi de la vérification d'erreur pour les opérations incorrec
|
||||
|
||||
<img src="/img/tutorial/body/image04.png">
|
||||
|
||||
Ce n'est pas un hasard, ce framework entier a été bati avec ce design comme objectif.
|
||||
Ce n'est pas un hasard, ce framework entier a été bâti avec ce design comme objectif.
|
||||
|
||||
Et cela a été rigoureusement testé durant la phase de design, avant toute implémentation, pour s'assurer que cela fonctionnerait avec tous les éditeurs.
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ Si vous créez votre app avec :
|
||||
{!../../../docs_src/first_steps/tutorial002.py!}
|
||||
```
|
||||
|
||||
Et la mettez dans un fichier `main.py`, alors vous appeleriez `uvicorn` avec :
|
||||
Et la mettez dans un fichier `main.py`, alors vous appelleriez `uvicorn` avec :
|
||||
|
||||
<div class="termy">
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ Ici, le paramètre `q` sera optionnel, et aura `None` comme valeur par défaut.
|
||||
!!! note
|
||||
**FastAPI** saura que `q` est optionnel grâce au `=None`.
|
||||
|
||||
Le `Optional` dans `Optional[str]` n'est pas utilisé par **FastAPI** (**FastAPI** n'en utilisera que la partie `str`), mais il servira tout de même à votre editeur de texte pour détecter des erreurs dans votre code.
|
||||
Le `Optional` dans `Optional[str]` n'est pas utilisé par **FastAPI** (**FastAPI** n'en utilisera que la partie `str`), mais il servira tout de même à votre éditeur de texte pour détecter des erreurs dans votre code.
|
||||
|
||||
|
||||
## Conversion des types des paramètres de requête
|
||||
|
||||
200
docs/ja/docs/deployment/https.md
Normal file
200
docs/ja/docs/deployment/https.md
Normal file
@@ -0,0 +1,200 @@
|
||||
# HTTPS について
|
||||
|
||||
HTTPSは単に「有効」か「無効」かで決まるものだと思いがちです。
|
||||
|
||||
しかし、それよりもはるかに複雑です。
|
||||
|
||||
!!! tip
|
||||
もし急いでいたり、HTTPSの仕組みについて気にしないのであれば、次のセクションに進み、さまざまなテクニックを使ってすべてをセットアップするステップ・バイ・ステップの手順をご覧ください。
|
||||
|
||||
利用者の視点から **HTTPS の基本を学ぶ**に当たっては、次のリソースをオススメします: <a href="https://howhttps.works/" class="external-link" target="_blank">https://howhttps.works/</a>.
|
||||
|
||||
さて、**開発者の視点**から、HTTPSについて考える際に念頭に置くべきことをいくつかみていきましょう:
|
||||
|
||||
* HTTPSの場合、**サーバ**は**第三者**によって生成された**「証明書」を持つ**必要があります。
|
||||
* これらの証明書は「生成」されたものではなく、実際には第三者から**取得**されたものです。
|
||||
* 証明書には**有効期限**があります。
|
||||
* つまりいずれ失効します。
|
||||
* そのため**更新**をし、第三者から**再度取得**する必要があります。
|
||||
* 接続の暗号化は**TCPレベル**で行われます。
|
||||
* それは**HTTPの1つ下**のレイヤーです。
|
||||
* つまり、**証明書と暗号化**の処理は、**HTTPの前**に行われます。
|
||||
* **TCPは "ドメイン "について知りません**。IPアドレスについてのみ知っています。
|
||||
* 要求された**特定のドメイン**に関する情報は、**HTTPデータ**に入ります。
|
||||
* **HTTPS証明書**は、**特定のドメイン**を「証明」しますが、プロトコルと暗号化はTCPレベルで行われ、どのドメインが扱われているかを**知る前**に行われます。
|
||||
* **デフォルトでは**、**IPアドレスごとに1つのHTTPS証明書**しか持てないことになります。
|
||||
* これは、サーバーの規模やアプリケーションの規模に寄りません。
|
||||
* しかし、これには**解決策**があります。
|
||||
* **TLS**プロトコル(HTTPの前に、TCPレベルで暗号化を処理するもの)には、**<a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="サーバー名表示">SNI</abbr></a>**と呼ばれる**拡張**があります。
|
||||
* このSNI拡張機能により、1つのサーバー(**単一のIPアドレス**を持つ)が**複数のHTTPS証明書**を持ち、**複数のHTTPSドメイン/アプリケーション**にサービスを提供できるようになります。
|
||||
* これが機能するためには、**パブリックIPアドレス**でリッスンしている、サーバー上で動作している**単一の**コンポーネント(プログラム)が、サーバー内の**すべてのHTTPS証明書**を持っている必要があります。
|
||||
|
||||
* セキュアな接続を取得した**後**でも、通信プロトコルは**HTTPのまま**です。
|
||||
* コンテンツは**HTTPプロトコル**で送信されているにもかかわらず、**暗号化**されています。
|
||||
|
||||
|
||||
サーバー(マシン、ホストなど)上で**1つのプログラム/HTTPサーバー**を実行させ、**HTTPSに関する全てのこと**を管理するのが一般的です。
|
||||
|
||||
**暗号化された HTTPS リクエスト** を受信し、**復号化された HTTP リクエスト** を同じサーバーで実行されている実際の HTTP アプリケーション(この場合は **FastAPI** アプリケーション)に送信し、アプリケーションから **HTTP レスポンス** を受け取り、適切な **HTTPS 証明書** を使用して **暗号化** し、そして**HTTPS** を使用してクライアントに送り返します。
|
||||
|
||||
このサーバーはしばしば **<a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">TLS Termination Proxy</a>**と呼ばれます。
|
||||
|
||||
TLS Termination Proxyとして使えるオプションには、以下のようなものがあります:
|
||||
|
||||
* Traefik(証明書の更新も対応)
|
||||
* Caddy (証明書の更新も対応)
|
||||
* Nginx
|
||||
* HAProxy
|
||||
|
||||
|
||||
## Let's Encrypt
|
||||
|
||||
Let's Encrypt以前は、これらの**HTTPS証明書**は信頼できる第三者によって販売されていました。
|
||||
|
||||
これらの証明書を取得するための手続きは面倒で、かなりの書類を必要とし、証明書はかなり高価なものでした。
|
||||
|
||||
しかしその後、**<a href="https://letsencrypt.org/" class="external-link" target="_blank">Let's Encrypt</a>** が作られました。
|
||||
|
||||
これはLinux Foundationのプロジェクトから生まれたものです。 自動化された方法で、**HTTPS証明書を無料で**提供します。これらの証明書は、すべての標準的な暗号化セキュリティを使用し、また短命(約3ヶ月)ですが、こういった寿命の短さによって、**セキュリティは実際に優れています**。
|
||||
|
||||
ドメインは安全に検証され、証明書は自動的に生成されます。また、証明書の更新も自動化されます。
|
||||
|
||||
このアイデアは、これらの証明書の取得と更新を自動化することで、**安全なHTTPSを、無料で、永遠に**利用できるようにすることです。
|
||||
|
||||
## 開発者のための HTTPS
|
||||
|
||||
ここでは、HTTPS APIがどのように見えるかの例を、主に開発者にとって重要なアイデアに注意を払いながら、ステップ・バイ・ステップで説明します。
|
||||
|
||||
### ドメイン名
|
||||
|
||||
ステップの初めは、**ドメイン名**を**取得すること**から始まるでしょう。その後、DNSサーバー(おそらく同じクラウドプロバイダー)に設定します。
|
||||
|
||||
おそらくクラウドサーバー(仮想マシン)かそれに類するものを手に入れ、<abbr title="変わらない">固定の</abbr> **パブリックIPアドレス**を持つことになるでしょう。
|
||||
|
||||
DNSサーバーでは、**取得したドメイン**をあなたのサーバーのパプリック**IPアドレス**に向けるレコード(「`Aレコード`」)を設定します。
|
||||
|
||||
これはおそらく、最初の1回だけあり、すべてをセットアップするときに行うでしょう。
|
||||
|
||||
!!! tip
|
||||
ドメイン名の話はHTTPSに関する話のはるか前にありますが、すべてがドメインとIPアドレスに依存するため、ここで言及する価値があります。
|
||||
|
||||
### DNS
|
||||
|
||||
では、実際のHTTPSの部分に注目してみよう。
|
||||
|
||||
まず、ブラウザは**DNSサーバー**に**ドメインに対するIP**が何であるかを確認します。今回は、`someapp.example.com`とします。
|
||||
|
||||
DNSサーバーは、ブラウザに特定の**IPアドレス**を使用するように指示します。このIPアドレスは、DNSサーバーで設定した、あなたのサーバーが使用するパブリックIPアドレスになります。
|
||||
|
||||
<img src="/img/deployment/https/https01.svg">
|
||||
|
||||
### TLS Handshake の開始
|
||||
|
||||
ブラウザはIPアドレスと**ポート443**(HTTPSポート)で通信します。
|
||||
|
||||
通信の最初の部分は、クライアントとサーバー間の接続を確立し、使用する暗号鍵などを決めるだけです。
|
||||
|
||||
<img src="/img/deployment/https/https02.svg">
|
||||
|
||||
TLS接続を確立するためのクライアントとサーバー間のこのやりとりは、**TLSハンドシェイク**と呼ばれます。
|
||||
|
||||
### SNI拡張機能付きのTLS
|
||||
|
||||
サーバー内の**1つのプロセス**だけが、特定 の**IPアドレス**の特定の**ポート** で待ち受けることができます。
|
||||
|
||||
同じIPアドレスの他のポートで他のプロセスがリッスンしている可能性もありますが、IPアドレスとポートの組み合わせごとに1つだけです。
|
||||
|
||||
TLS(HTTPS)はデフォルトで`443`という特定のポートを使用する。つまり、これが必要なポートです。
|
||||
|
||||
このポートをリッスンできるのは1つのプロセスだけなので、これを実行するプロセスは**TLS Termination Proxy**となります。
|
||||
|
||||
TLS Termination Proxyは、1つ以上の**TLS証明書**(HTTPS証明書)にアクセスできます。
|
||||
|
||||
前述した**SNI拡張機能**を使用して、TLS Termination Proxy は、利用可能なTLS (HTTPS)証明書のどれを接続先として使用すべきかをチェックし、クライアントが期待するドメインに一致するものを使用します。
|
||||
|
||||
今回は、`someapp.example.com`の証明書を使うことになります。
|
||||
|
||||
<img src="/img/deployment/https/https03.svg">
|
||||
|
||||
クライアントは、そのTLS証明書を生成したエンティティ(この場合はLet's Encryptですが、これについては後述します)をすでに**信頼**しているため、その証明書が有効であることを**検証**することができます。
|
||||
|
||||
次に証明書を使用して、クライアントとTLS Termination Proxy は、 **TCP通信**の残りを**どのように暗号化するかを決定**します。これで**TLSハンドシェイク**の部分が完了します。
|
||||
|
||||
この後、クライアントとサーバーは**暗号化されたTCP接続**を持ちます。そして、その接続を使って実際の**HTTP通信**を開始することができます。
|
||||
|
||||
これが**HTTPS**であり、純粋な(暗号化されていない)TCP接続ではなく、**セキュアなTLS接続**の中に**HTTP**があるだけです。
|
||||
|
||||
!!! tip
|
||||
通信の暗号化は、HTTPレベルではなく、**TCPレベル**で行われることに注意してください。
|
||||
|
||||
### HTTPS リクエスト
|
||||
|
||||
これでクライアントとサーバー(具体的にはブラウザとTLS Termination Proxy)は**暗号化されたTCP接続**を持つことになり、**HTTP通信**を開始することができます。
|
||||
|
||||
そこで、クライアントは**HTTPSリクエスト**を送信します。これは、暗号化されたTLSコネクションを介した単なるHTTPリクエストです。
|
||||
|
||||
<img src="/img/deployment/https/https04.svg">
|
||||
|
||||
### リクエストの復号化
|
||||
|
||||
TLS Termination Proxy は、合意が取れている暗号化を使用して、**リクエストを復号化**し、**プレーン (復号化された) HTTP リクエスト** をアプリケーションを実行しているプロセス (例えば、FastAPI アプリケーションを実行している Uvicorn を持つプロセス) に送信します。
|
||||
|
||||
<img src="/img/deployment/https/https05.svg">
|
||||
|
||||
### HTTP レスポンス
|
||||
|
||||
アプリケーションはリクエストを処理し、**プレーン(暗号化されていない)HTTPレスポンス** をTLS Termination Proxyに送信します。
|
||||
|
||||
<img src="/img/deployment/https/https06.svg">
|
||||
|
||||
### HTTPS レスポンス
|
||||
|
||||
TLS Termination Proxyは次に、事前に合意が取れている暗号(`someapp.example.com`の証明書から始まる)を使って**レスポンスを暗号化し**、ブラウザに送り返す。
|
||||
|
||||
その後ブラウザでは、レスポンスが有効で正しい暗号キーで暗号化されていることなどを検証します。そして、ブラウザはレスポンスを**復号化**して処理します。
|
||||
|
||||
<img src="/img/deployment/https/https07.svg">
|
||||
|
||||
クライアント(ブラウザ)は、レスポンスが正しいサーバーから来たことを知ることができます。 なぜなら、そのサーバーは、以前に**HTTPS証明書**を使って合意した暗号を使っているからです。
|
||||
|
||||
### 複数のアプリケーション
|
||||
|
||||
同じサーバー(または複数のサーバー)に、例えば他のAPIプログラムやデータベースなど、**複数のアプリケーション**が存在する可能性があります。
|
||||
|
||||
特定のIPとポート(この例ではTLS Termination Proxy)を扱うことができるのは1つのプロセスだけですが、他のアプリケーション/プロセスも、同じ**パブリックIPとポート**の組み合わせを使用しようとしない限り、サーバー上で実行することができます。
|
||||
|
||||
<img src="/img/deployment/https/https08.svg">
|
||||
|
||||
そうすれば、TLS Termination Proxy は、**複数のドメイン**や複数のアプリケーションのHTTPSと証明書を処理し、それぞれのケースで適切なアプリケーションにリクエストを送信することができます。
|
||||
|
||||
### 証明書の更新
|
||||
|
||||
将来のある時点で、各証明書は(取得後約3ヶ月で)**失効**します。
|
||||
|
||||
その後、Let's Encryptと通信する別のプログラム(別のプログラムである場合もあれば、同じTLS Termination Proxyである場合もある)によって、証明書を更新します。
|
||||
|
||||
<img src="/img/deployment/https/https.svg">
|
||||
|
||||
**TLS証明書**は、IPアドレスではなく、**ドメイン名に関連付けられて**います。
|
||||
|
||||
したがって、証明書を更新するために、更新プログラムは、認証局(Let's Encrypt)に対して、**そのドメインが本当に「所有」し、管理している**ことを**証明**する必要があります。
|
||||
|
||||
そのために、またさまざまなアプリケーションのニーズに対応するために、いくつかの方法があります。よく使われる方法としては:
|
||||
|
||||
* **いくつかのDNSレコードを修正します。**
|
||||
* これをするためには、更新プログラムはDNSプロバイダーのAPIをサポートする必要があります。したがって、使用しているDNSプロバイダーによっては、このオプションが使える場合もあれば、使えない場合もあります。
|
||||
* ドメインに関連付けられたパブリックIPアドレス上で、(少なくとも証明書取得プロセス中は)**サーバー**として実行します。
|
||||
* 上で述べたように、特定のIPとポートでリッスンできるプロセスは1つだけです。
|
||||
* これは、同じTLS Termination Proxyが証明書の更新処理も行う場合に非常に便利な理由の1つです。
|
||||
* そうでなければ、TLS Termination Proxyを一時的に停止し、証明書を取得するために更新プログラムを起動し、TLS Termination Proxyで証明書を設定し、TLS Termination Proxyを再起動しなければならないかもしれません。TLS Termination Proxyが停止している間はアプリが利用できなくなるため、これは理想的ではありません。
|
||||
|
||||
|
||||
アプリを提供しながらこのような更新処理を行うことは、アプリケーション・サーバー(Uvicornなど)でTLS証明書を直接使用するのではなく、TLS Termination Proxyを使用して**HTTPSを処理する別のシステム**を用意したくなる主な理由の1つです。
|
||||
|
||||
## まとめ
|
||||
|
||||
**HTTPS**を持つことは非常に重要であり、ほとんどの場合、かなり**クリティカル**です。開発者として HTTPS に関わる労力のほとんどは、これらの**概念とその仕組みを理解する**ことです。
|
||||
|
||||
しかし、ひとたび**開発者向けHTTPS**の基本的な情報を知れば、簡単な方法ですべてを管理するために、さまざまなツールを組み合わせて設定することができます。
|
||||
|
||||
次の章では、**FastAPI** アプリケーションのために **HTTPS** をセットアップする方法について、いくつかの具体例を紹介します。🔒
|
||||
17
docs/ko/docs/deployment/cloud.md
Normal file
17
docs/ko/docs/deployment/cloud.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# FastAPI를 클라우드 제공업체에서 배포하기
|
||||
|
||||
사실상 거의 **모든 클라우드 제공업체**를 사용하여 여러분의 FastAPI 애플리케이션을 배포할 수 있습니다.
|
||||
|
||||
대부분의 경우, 주요 클라우드 제공업체에서는 FastAPI를 배포할 수 있도록 가이드를 제공합니다.
|
||||
|
||||
## 클라우드 제공업체 - 후원자들
|
||||
|
||||
몇몇 클라우드 제공업체들은 [**FastAPI를 후원하며**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, 이를 통해 FastAPI와 FastAPI **생태계**가 지속적이고 건전한 **발전**을 할 수 있습니다.
|
||||
|
||||
이는 FastAPI와 **커뮤니티** (여러분)에 대한 진정한 헌신을 보여줍니다. 그들은 여러분에게 **좋은 서비스**를 제공할 뿐 만이 아니라 여러분이 **훌륭하고 건강한 프레임워크인** FastAPI 를 사용하길 원하기 때문입니다. 🙇
|
||||
|
||||
아래와 같은 서비스를 사용해보고 각 서비스의 가이드를 따를 수도 있습니다:
|
||||
|
||||
* <a href="https://docs.platform.sh/languages/python.html?utm_source=fastapi-signup&utm_medium=banner&utm_campaign=FastAPI-signup-June-2023" class="external-link" target="_blank">Platform.sh</a>
|
||||
* <a href="https://docs.porter.run/language-specific-guides/fastapi" class="external-link" target="_blank">Porter</a>
|
||||
* <a href="https://www.deta.sh/?ref=fastapi" class="external-link" target="_blank">Deta</a>
|
||||
265
docs/pl/docs/help-fastapi.md
Normal file
265
docs/pl/docs/help-fastapi.md
Normal file
@@ -0,0 +1,265 @@
|
||||
# Pomóż FastAPI - Uzyskaj pomoc
|
||||
|
||||
Czy podoba Ci się **FastAPI**?
|
||||
|
||||
Czy chciałbyś pomóc FastAPI, jego użytkownikom i autorowi?
|
||||
|
||||
Może napotkałeś na trudności z **FastAPI** i potrzebujesz pomocy?
|
||||
|
||||
Istnieje kilka bardzo łatwych sposobów, aby pomóc (czasami wystarczy jedno lub dwa kliknięcia).
|
||||
|
||||
Istnieje również kilka sposobów uzyskania pomocy.
|
||||
|
||||
## Zapisz się do newslettera
|
||||
|
||||
Możesz zapisać się do rzadkiego [newslettera o **FastAPI i jego przyjaciołach**](/newsletter/){.internal-link target=_blank}, aby być na bieżąco z:
|
||||
|
||||
* Aktualnościami o FastAPI i przyjaciołach 🚀
|
||||
* Przewodnikami 📝
|
||||
* Funkcjami ✨
|
||||
* Przełomowymi zmianami 🚨
|
||||
* Poradami i sztuczkami ✅
|
||||
|
||||
## Śledź FastAPI na Twitterze
|
||||
|
||||
<a href="https://twitter.com/fastapi" class="external-link" target="_blank">Śledź @fastapi na **Twitterze**</a> aby być na bieżąco z najnowszymi wiadomościami o **FastAPI**. 🐦
|
||||
|
||||
## Dodaj gwiazdkę **FastAPI** na GitHubie
|
||||
|
||||
Możesz "dodać gwiazdkę" FastAPI na GitHubie (klikając przycisk gwiazdki w prawym górnym rogu): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>. ⭐️
|
||||
|
||||
Dodając gwiazdkę, inni użytkownicy będą mogli łatwiej znaleźć projekt i zobaczyć, że był już przydatny dla innych.
|
||||
|
||||
## Obserwuj repozytorium GitHub w poszukiwaniu nowych wydań
|
||||
|
||||
Możesz "obserwować" FastAPI na GitHubie (klikając przycisk "obserwuj" w prawym górnym rogu): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>. 👀
|
||||
|
||||
Wybierz opcję "Tylko wydania".
|
||||
|
||||
Dzięki temu będziesz otrzymywać powiadomienia (na swój adres e-mail) za każdym razem, gdy pojawi się nowe wydanie (nowa wersja) **FastAPI** z poprawkami błędów i nowymi funkcjami.
|
||||
|
||||
## Skontaktuj się z autorem
|
||||
|
||||
Możesz skontaktować się <a href="https://tiangolo.com" class="external-link" target="_blank">ze mną (Sebastián Ramírez / `tiangolo`)</a>, autorem.
|
||||
|
||||
Możesz:
|
||||
|
||||
* <a href="https://github.com/tiangolo" class="external-link" target="_blank">Śledzić mnie na **GitHubie**</a>.
|
||||
* Zobacz inne projekty open source, które stworzyłem, a mogą być dla Ciebie pomocne.
|
||||
* Śledź mnie, aby dostać powiadomienie, gdy utworzę nowy projekt open source.
|
||||
* <a href="https://twitter.com/tiangolo" class="external-link" target="_blank">Śledzić mnie na **Twitterze**</a> lub na <a href="https://fosstodon.org/@tiangolo" class="external-link" target="_blank">Mastodonie</a>.
|
||||
* Napisz mi, w jaki sposób korzystasz z FastAPI (uwielbiam o tym czytać).
|
||||
* Dowiedz się, gdy ogłoszę coś nowego lub wypuszczę nowe narzędzia.
|
||||
* Możesz także <a href="https://twitter.com/fastapi" class="external-link" target="_blank">śledzić @fastapi na Twitterze</a> (to oddzielne konto).
|
||||
* <a href="https://www.linkedin.com/in/tiangolo/" class="external-link" target="_blank">Nawiąż ze mną kontakt na **Linkedinie**</a>.
|
||||
* Dowiedz się, gdy ogłoszę coś nowego lub wypuszczę nowe narzędzia (chociaż częściej korzystam z Twittera 🤷♂).
|
||||
* Czytaj moje posty (lub śledź mnie) na <a href="https://dev.to/tiangolo" class="external-link" target="_blank">**Dev.to**</a> lub na <a href="https://medium.com/@tiangolo" class="external-link" target="_blank">**Medium**</a>.
|
||||
* Czytaj o innych pomysłach, artykułach i dowiedz się o narzędziach, które stworzyłem.
|
||||
* Śledź mnie, by wiedzieć gdy opublikuję coś nowego.
|
||||
|
||||
## Napisz tweeta o **FastAPI**
|
||||
|
||||
<a href="https://twitter.com/compose/tweet?text=I'm loving @fastapi because... https://github.com/tiangolo/fastapi" class="external-link" target="_blank">Napisz tweeta o **FastAPI**</a> i powiedz czemu Ci się podoba. 🎉
|
||||
|
||||
Uwielbiam czytać w jaki sposób **FastAPI** jest używane, co Ci się w nim podobało, w jakim projekcie/firmie go używasz itp.
|
||||
|
||||
## Głosuj na FastAPI
|
||||
|
||||
* <a href="https://www.slant.co/options/34241/~fastapi-review" class="external-link" target="_blank">Głosuj na **FastAPI** w Slant</a>.
|
||||
* <a href="https://alternativeto.net/software/fastapi/" class="external-link" target="_blank">Głosuj na **FastAPI** w AlternativeTo</a>.
|
||||
* <a href="https://stackshare.io/pypi-fastapi" class="external-link" target="_blank">Powiedz, że używasz **FastAPI** na StackShare</a>.
|
||||
|
||||
## Pomagaj innym, odpowiadając na ich pytania na GitHubie
|
||||
|
||||
Możesz spróbować pomóc innym, odpowiadając w:
|
||||
|
||||
* <a href="https://github.com/tiangolo/fastapi/discussions/categories/questions?discussions_q=category%3AQuestions+is%3Aunanswered" class="external-link" target="_blank">Dyskusjach na GitHubie</a>
|
||||
* <a href="https://github.com/tiangolo/fastapi/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Aquestion+-label%3Aanswered+" class="external-link" target="_blank">Problemach na GitHubie</a>
|
||||
|
||||
W wielu przypadkach możesz już znać odpowiedź na te pytania. 🤓
|
||||
|
||||
Jeśli pomożesz wielu ludziom, możesz zostać oficjalnym [Ekspertem FastAPI](fastapi-people.md#experts){.internal-link target=_blank}. 🎉
|
||||
|
||||
Pamiętaj tylko o najważniejszym: bądź życzliwy. Ludzie przychodzą sfrustrowani i w wielu przypadkach nie zadają pytań w najlepszy sposób, ale mimo to postaraj się być dla nich jak najbardziej życzliwy. 🤗
|
||||
|
||||
Chciałbym, by społeczność **FastAPI** była życzliwa i przyjazna. Nie akceptuj prześladowania ani braku szacunku wobec innych. Dbajmy o siebie nawzajem.
|
||||
|
||||
---
|
||||
|
||||
Oto, jak pomóc innym z pytaniami (w dyskusjach lub problemach):
|
||||
|
||||
### Zrozum pytanie
|
||||
|
||||
* Upewnij się, czy rozumiesz **cel** i przypadek użycia osoby pytającej.
|
||||
|
||||
* Następnie sprawdź, czy pytanie (większość to pytania) jest **jasne**.
|
||||
|
||||
* W wielu przypadkach zadane pytanie dotyczy rozwiązania wymyślonego przez użytkownika, ale może istnieć **lepsze** rozwiązanie. Jeśli dokładnie zrozumiesz problem i przypadek użycia, być może będziesz mógł zaproponować lepsze **alternatywne rozwiązanie**.
|
||||
|
||||
* Jeśli nie rozumiesz pytania, poproś o więcej **szczegółów**.
|
||||
|
||||
### Odtwórz problem
|
||||
|
||||
W większości przypadków problem wynika z **autorskiego kodu** osoby pytającej.
|
||||
|
||||
Często pytający umieszczają tylko fragment kodu, niewystarczający do **odtworzenia problemu**.
|
||||
|
||||
* Możesz poprosić ich o dostarczenie <a href="https://stackoverflow.com/help/minimal-reproducible-example" class="external-link" target="_blank">minimalnego, odtwarzalnego przykładu</a>, który możesz **skopiować i wkleić** i uruchomić lokalnie, aby zobaczyć ten sam błąd lub zachowanie, które widzą, lub lepiej zrozumieć ich przypadki użycia.
|
||||
|
||||
* Jeśli jesteś wyjątkowo pomocny, możesz spróbować **stworzyć taki przykład** samodzielnie, opierając się tylko na opisie problemu. Miej na uwadze, że może to zająć dużo czasu i lepiej może być najpierw poprosić ich o wyjaśnienie problemu.
|
||||
|
||||
### Proponuj rozwiązania
|
||||
|
||||
* Po zrozumieniu pytania możesz podać im możliwą **odpowiedź**.
|
||||
|
||||
* W wielu przypadkach lepiej zrozumieć ich **podstawowy problem lub przypadek użycia**, ponieważ może istnieć lepszy sposób rozwiązania niż to, co próbują zrobić.
|
||||
|
||||
### Poproś o zamknięcie
|
||||
|
||||
Jeśli odpowiedzą, jest duża szansa, że rozwiązałeś ich problem, gratulacje, **jesteś bohaterem**! 🦸
|
||||
|
||||
* Jeśli Twoja odpowiedź rozwiązała problem, możesz poprosić o:
|
||||
|
||||
* W Dyskusjach na GitHubie: oznaczenie komentarza jako **odpowiedź**.
|
||||
* W Problemach na GitHubie: **zamknięcie** problemu.
|
||||
|
||||
## Obserwuj repozytorium na GitHubie
|
||||
|
||||
Możesz "obserwować" FastAPI na GitHubie (klikając przycisk "obserwuj" w prawym górnym rogu): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>. 👀
|
||||
|
||||
Jeśli wybierzesz "Obserwuj" zamiast "Tylko wydania", otrzymasz powiadomienia, gdy ktoś utworzy nowy problem lub pytanie. Możesz również określić, że chcesz być powiadamiany tylko o nowych problemach, dyskusjach, PR-ach itp.
|
||||
|
||||
Następnie możesz spróbować pomóc rozwiązać te problemy.
|
||||
|
||||
## Zadawaj pytania
|
||||
|
||||
Możesz <a href="https://github.com/tiangolo/fastapi/discussions/new?category=questions" class="external-link" target="_blank">utworzyć nowe pytanie</a> w repozytorium na GitHubie, na przykład aby:
|
||||
|
||||
* Zadać **pytanie** lub zapytać o **problem**.
|
||||
* Zaproponować nową **funkcję**.
|
||||
|
||||
**Uwaga**: jeśli to zrobisz, poproszę Cię również o pomoc innym. 😉
|
||||
|
||||
## Przeglądaj Pull Requesty
|
||||
|
||||
Możesz pomóc mi w przeglądaniu pull requestów autorstwa innych osób.
|
||||
|
||||
Jak wcześniej wspomniałem, postaraj się być jak najbardziej życzliwy. 🤗
|
||||
|
||||
---
|
||||
|
||||
Oto, co warto mieć na uwadze podczas oceny pull requestu:
|
||||
|
||||
### Zrozum problem
|
||||
|
||||
* Najpierw upewnij się, że **rozumiesz problem**, który próbuje rozwiązać pull request. Może być osadzony w większym kontekście w GitHubowej dyskusji lub problemie.
|
||||
|
||||
* Jest też duża szansa, że pull request nie jest konieczny, ponieważ problem można rozwiązać w **inny sposób**. Wtedy możesz to zasugerować lub o to zapytać.
|
||||
|
||||
### Nie martw się stylem
|
||||
|
||||
* Nie przejmuj się zbytnio rzeczami takimi jak style wiadomości commitów, przy wcielaniu pull requesta łączę commity i modyfikuję opis sumarycznego commita ręcznie.
|
||||
|
||||
* Nie przejmuj się również stylem kodu, automatyczne narzędzia w repozytorium sprawdzają to samodzielnie.
|
||||
|
||||
A jeśli istnieje jakaś konkretna potrzeba dotycząca stylu lub spójności, sam poproszę o zmiany lub dodam commity z takimi zmianami.
|
||||
|
||||
### Sprawdź kod
|
||||
|
||||
* Przeczytaj kod, zastanów się czy ma sens, **uruchom go lokalnie** i potwierdź czy faktycznie rozwiązuje problem.
|
||||
|
||||
* Następnie dodaj **komentarz** z informacją o tym, że sprawdziłeś kod, dzięki temu będę miał pewność, że faktycznie go sprawdziłeś.
|
||||
|
||||
!!! info
|
||||
Niestety, nie mogę ślepo ufać PR-om, nawet jeśli mają kilka zatwierdzeń.
|
||||
|
||||
Kilka razy zdarzyło się, że PR-y miały 3, 5 lub więcej zatwierdzeń (prawdopodobnie dlatego, że opis obiecuje rozwiązanie ważnego problemu), ale gdy sam sprawdziłem danego PR-a, okazał się być zbugowany lub nie rozwiązywał problemu, który rzekomo miał rozwiązywać. 😅
|
||||
|
||||
Dlatego tak ważne jest, abyś faktycznie przeczytał i uruchomił kod oraz napisał w komentarzu, że to zrobiłeś. 🤓
|
||||
|
||||
* Jeśli PR można uprościć w jakiś sposób, możesz o to poprosić, ale nie ma potrzeby być zbyt wybrednym, może być wiele subiektywnych punktów widzenia (a ja też będę miał swój 🙈), więc lepiej żebyś skupił się na kluczowych rzeczach.
|
||||
|
||||
### Testy
|
||||
|
||||
* Pomóż mi sprawdzić, czy PR ma **testy**.
|
||||
|
||||
* Sprawdź, czy testy **nie przechodzą** przed PR. 🚨
|
||||
|
||||
* Następnie sprawdź, czy testy **przechodzą** po PR. ✅
|
||||
|
||||
* Wiele PR-ów nie ma testów, możesz **przypomnieć** im o dodaniu testów, a nawet **zaproponować** samemu jakieś testy. To jedna z rzeczy, które pochłaniają najwięcej czasu i możesz w tym bardzo pomóc.
|
||||
|
||||
* Następnie skomentuj również to, czego spróbowałeś, wtedy będę wiedział, że to sprawdziłeś. 🤓
|
||||
|
||||
## Utwórz Pull Request
|
||||
|
||||
Możesz [wnieść wkład](contributing.md){.internal-link target=_blank} do kodu źródłowego za pomocą Pull Requestu, na przykład:
|
||||
|
||||
* Naprawić literówkę, którą znalazłeś w dokumentacji.
|
||||
* Podzielić się artykułem, filmem lub podcastem, który stworzyłeś lub znalazłeś na temat FastAPI, <a href="https://github.com/tiangolo/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">edytując ten plik</a>.
|
||||
* Upewnij się, że dodajesz swój link na początku odpowiedniej sekcji.
|
||||
* Pomóc w [tłumaczeniu dokumentacji](contributing.md#translations){.internal-link target=_blank} na Twój język.
|
||||
* Możesz również pomóc w weryfikacji tłumaczeń stworzonych przez innych.
|
||||
* Zaproponować nowe sekcje dokumentacji.
|
||||
* Naprawić istniejący problem/błąd.
|
||||
* Upewnij się, że dodajesz testy.
|
||||
* Dodać nową funkcję.
|
||||
* Upewnij się, że dodajesz testy.
|
||||
* Upewnij się, że dodajesz dokumentację, jeśli jest to istotne.
|
||||
|
||||
## Pomóż w utrzymaniu FastAPI
|
||||
|
||||
Pomóż mi utrzymać **FastAPI**! 🤓
|
||||
|
||||
Jest wiele pracy do zrobienia, a w większości przypadków **TY** możesz to zrobić.
|
||||
|
||||
Główne zadania, które możesz wykonać teraz to:
|
||||
|
||||
* [Pomóc innym z pytaniami na GitHubie](#help-others-with-questions-in-github){.internal-link target=_blank} (zobacz sekcję powyżej).
|
||||
* [Oceniać Pull Requesty](#review-pull-requests){.internal-link target=_blank} (zobacz sekcję powyżej).
|
||||
|
||||
Te dwie czynności **zajmują najwięcej czasu**. To główna praca związana z utrzymaniem FastAPI.
|
||||
|
||||
Jeśli możesz mi w tym pomóc, **pomożesz mi utrzymać FastAPI** i zapewnisz że będzie **rozwijać się szybciej i lepiej**. 🚀
|
||||
|
||||
## Dołącz do czatu
|
||||
|
||||
Dołącz do 👥 <a href="https://discord.gg/VQjSZaeJmf" class="external-link" target="_blank">serwera czatu na Discordzie</a> 👥 i spędzaj czas z innymi w społeczności FastAPI.
|
||||
|
||||
!!! wskazówka
|
||||
Jeśli masz pytania, zadaj je w <a href="https://github.com/tiangolo/fastapi/discussions/new?category=questions" class="external-link" target="_blank">Dyskusjach na GitHubie</a>, jest dużo większa szansa, że otrzymasz pomoc od [Ekspertów FastAPI](fastapi-people.md#experts){.internal-link target=_blank}.
|
||||
|
||||
Używaj czatu tylko do innych ogólnych rozmów.
|
||||
|
||||
Istnieje również poprzedni <a href="https://gitter.im/tiangolo/fastapi" class="external-link" target="_blank">czat na Gitter</a>, ale ponieważ nie ma tam kanałów i zaawansowanych funkcji, rozmowy są trudniejsze, dlatego teraz zalecany jest Discord.
|
||||
|
||||
### Nie zadawaj pytań na czacie
|
||||
|
||||
Miej na uwadze, że ponieważ czaty pozwalają na bardziej "swobodną rozmowę", łatwo jest zadawać pytania, które są zbyt ogólne i trudniejsze do odpowiedzi, więc możesz nie otrzymać odpowiedzi.
|
||||
|
||||
Na GitHubie szablon poprowadzi Cię do napisania odpowiedniego pytania, dzięki czemu łatwiej uzyskasz dobrą odpowiedź, a nawet rozwiążesz problem samodzielnie, zanim zapytasz. Ponadto na GitHubie mogę się upewnić, że zawsze odpowiadam na wszystko, nawet jeśli zajmuje to trochę czasu. Osobiście nie mogę tego zrobić z systemami czatu. 😅
|
||||
|
||||
Rozmów w systemach czatu nie można tak łatwo przeszukiwać, jak na GitHubie, więc pytania i odpowiedzi mogą zaginąć w rozmowie. A tylko te na GitHubie liczą się do zostania [Ekspertem FastAPI](fastapi-people.md#experts){.internal-link target=_blank}, więc najprawdopodobniej otrzymasz więcej uwagi na GitHubie.
|
||||
|
||||
Z drugiej strony w systemach czatu są tysiące użytkowników, więc jest duża szansa, że znajdziesz tam kogoś do rozmowy, prawie w każdej chwili. 😄
|
||||
|
||||
## Wspieraj autora
|
||||
|
||||
Możesz również finansowo wesprzeć autora (mnie) poprzez <a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">sponsoring na GitHubie</a>.
|
||||
|
||||
Tam możesz postawić mi kawę ☕️ aby podziękować. 😄
|
||||
|
||||
Możesz także zostać srebrnym lub złotym sponsorem FastAPI. 🏅🎉
|
||||
|
||||
## Wspieraj narzędzia, które napędzają FastAPI
|
||||
|
||||
Jak widziałeś w dokumentacji, FastAPI stoi na ramionach gigantów, Starlette i Pydantic.
|
||||
|
||||
Możesz również wesprzeć:
|
||||
|
||||
* <a href="https://github.com/sponsors/samuelcolvin" class="external-link" target="_blank">Samuel Colvin (Pydantic)</a>
|
||||
* <a href="https://github.com/sponsors/encode" class="external-link" target="_blank">Encode (Starlette, Uvicorn)</a>
|
||||
|
||||
---
|
||||
|
||||
Dziękuję! 🚀
|
||||
@@ -236,7 +236,6 @@ Então, você poderia usar ele com:
|
||||
Com o **FastAPI**, usando as declarações de tipo do Python, você obtém:
|
||||
|
||||
* Suporte no editor: verificação de erros, e opção de autocompletar, etc.
|
||||
* Parsing de dados
|
||||
* "<abbr title="convertendo uma string que vem de um request HTTP em dado Python">Parsing</abbr>" de dados
|
||||
* Validação de dados
|
||||
* Anotação da API e documentação automática
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
{!> ../../../docs_src/body_fields/tutorial001.py!}
|
||||
```
|
||||
|
||||
Функция `Field` работает так же, как `Query`, `Path` и `Body`, у ее такие же параметры и т.д.
|
||||
Функция `Field` работает так же, как `Query`, `Path` и `Body`, у неё такие же параметры и т.д.
|
||||
|
||||
!!! note "Технические детали"
|
||||
На самом деле, `Query`, `Path` и другие функции, которые вы увидите в дальнейшем, создают объекты подклассов общего класса `Param`, который сам по себе является подклассом `FieldInfo` из Pydantic.
|
||||
|
||||
227
docs/ru/docs/tutorial/header-params.md
Normal file
227
docs/ru/docs/tutorial/header-params.md
Normal file
@@ -0,0 +1,227 @@
|
||||
# Header-параметры
|
||||
|
||||
Вы можете определить параметры заголовка таким же образом, как вы определяете параметры `Query`, `Path` и `Cookie`.
|
||||
|
||||
## Импорт `Header`
|
||||
|
||||
Сперва импортируйте `Header`:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/header_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
## Объявление параметров `Header`
|
||||
|
||||
Затем объявите параметры заголовка, используя ту же структуру, что и с `Path`, `Query` и `Cookie`.
|
||||
|
||||
Первое значение является значением по умолчанию, вы можете передать все дополнительные параметры валидации или аннотации:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note "Технические детали"
|
||||
`Header` - это "родственный" класс `Path`, `Query` и `Cookie`. Он также наследуется от того же общего класса `Param`.
|
||||
|
||||
Но помните, что когда вы импортируете `Query`, `Path`, `Header` и другие из `fastapi`, на самом деле это функции, которые возвращают специальные классы.
|
||||
|
||||
!!! info "Дополнительная информация"
|
||||
Чтобы объявить заголовки, важно использовать `Header`, иначе параметры интерпретируются как query-параметры.
|
||||
|
||||
## Автоматическое преобразование
|
||||
|
||||
`Header` обладает небольшой дополнительной функциональностью в дополнение к тому, что предоставляют `Path`, `Query` и `Cookie`.
|
||||
|
||||
Большинство стандартных заголовков разделены символом "дефис", также известным как "минус" (`-`).
|
||||
|
||||
Но переменная вроде `user-agent` недопустима в Python.
|
||||
|
||||
По умолчанию `Header` преобразует символы имен параметров из символа подчеркивания (`_`) в дефис (`-`) для извлечения и документирования заголовков.
|
||||
|
||||
Кроме того, HTTP-заголовки не чувствительны к регистру, поэтому вы можете объявить их в стандартном стиле Python (также известном как "snake_case").
|
||||
|
||||
Таким образом вы можете использовать `user_agent`, как обычно, в коде Python, вместо того, чтобы вводить заглавные буквы как `User_Agent` или что-то подобное.
|
||||
|
||||
Если по какой-либо причине вам необходимо отключить автоматическое преобразование подчеркиваний в дефисы, установите для параметра `convert_underscores` в `Header` значение `False`:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/header_params/tutorial002_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/header_params/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/header_params/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/header_params/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/header_params/tutorial002.py!}
|
||||
```
|
||||
|
||||
!!! warning "Внимание"
|
||||
Прежде чем установить для `convert_underscores` значение `False`, имейте в виду, что некоторые HTTP-прокси и серверы запрещают использование заголовков с подчеркиванием.
|
||||
|
||||
## Повторяющиеся заголовки
|
||||
|
||||
Есть возможность получать несколько заголовков с одним и тем же именем, но разными значениями.
|
||||
|
||||
Вы можете определить эти случаи, используя список в объявлении типа.
|
||||
|
||||
Вы получите все значения из повторяющегося заголовка в виде `list` Python.
|
||||
|
||||
Например, чтобы объявить заголовок `X-Token`, который может появляться более одного раза, вы можете написать:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial003_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial003_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/header_params/tutorial003_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/header_params/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial003_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```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** позаботится об их преобразовании.
|
||||
412
docs/uk/docs/alternatives.md
Normal file
412
docs/uk/docs/alternatives.md
Normal file
@@ -0,0 +1,412 @@
|
||||
# Альтернативи, натхнення та порівняння
|
||||
|
||||
Що надихнуло на створення **FastAPI**, який він у порінянні з іншими альтернативами та чого він у них навчився.
|
||||
|
||||
## Вступ
|
||||
|
||||
**FastAPI** не існувало б, якби не попередні роботи інших.
|
||||
|
||||
Раніше було створено багато інструментів, які надихнули на його створення.
|
||||
|
||||
Я кілька років уникав створення нового фреймворку. Спочатку я спробував вирішити всі функції, охоплені **FastAPI**, використовуючи багато різних фреймворків, плагінів та інструментів.
|
||||
|
||||
Але в якийсь момент не було іншого виходу, окрім створення чогось, що надавало б усі ці функції, взявши найкращі ідеї з попередніх інструментів і поєднавши їх найкращим чином, використовуючи мовні функції, які навіть не були доступні раніше (Python 3.6+ підказки типів).
|
||||
|
||||
## Попередні інструменти
|
||||
|
||||
### <a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a>
|
||||
|
||||
Це найпопулярніший фреймворк Python, який користується широкою довірою. Він використовується для створення таких систем, як Instagram.
|
||||
|
||||
Він відносно тісно пов’язаний з реляційними базами даних (наприклад, MySQL або PostgreSQL), тому мати базу даних NoSQL (наприклад, Couchbase, MongoDB, Cassandra тощо) як основний механізм зберігання не дуже просто.
|
||||
|
||||
Він був створений для створення HTML у серверній частині, а не для створення API, які використовуються сучасним інтерфейсом (як-от React, Vue.js і Angular) або іншими системами (як-от <abbr title="Internet of Things">IoT</abbr > пристрої), які спілкуються з ним.
|
||||
|
||||
### <a href="https://www.django-rest-framework.org/" class="external-link" target="_blank">Django REST Framework</a>
|
||||
|
||||
Фреймворк Django REST був створений як гнучкий інструментарій для створення веб-інтерфейсів API використовуючи Django в основі, щоб покращити його можливості API.
|
||||
|
||||
Його використовують багато компаній, включаючи Mozilla, Red Hat і Eventbrite.
|
||||
|
||||
Це був один із перших прикладів **автоматичної документації API**, і саме це була одна з перших ідей, яка надихнула на «пошук» **FastAPI**.
|
||||
|
||||
!!! Примітка
|
||||
Django REST Framework створив Том Крісті. Той самий творець Starlette і Uvicorn, на яких базується **FastAPI**.
|
||||
|
||||
|
||||
!!! Перегляньте "Надихнуло **FastAPI** на"
|
||||
Мати автоматичний веб-інтерфейс документації API.
|
||||
|
||||
### <a href="https://flask.palletsprojects.com" class="external-link" target="_blank">Flask</a>
|
||||
|
||||
Flask — це «мікрофреймворк», він не включає інтеграцію бази даних, а також багато речей, які за замовчуванням є в Django.
|
||||
|
||||
Ця простота та гнучкість дозволяють використовувати бази даних NoSQL як основну систему зберігання даних.
|
||||
|
||||
Оскільки він дуже простий, він порівняно легкий та інтуїтивний для освоєння, хоча в деяких моментах документація стає дещо технічною.
|
||||
|
||||
Він також зазвичай використовується для інших програм, яким не обов’язково потрібна база даних, керування користувачами або будь-яка з багатьох функцій, які є попередньо вбудованими в Django. Хоча багато з цих функцій можна додати за допомогою плагінів.
|
||||
|
||||
Відокремлення частин було ключовою особливістю, яку я хотів зберегти, при цьому залишаючись «мікрофреймворком», який можна розширити, щоб охопити саме те, що потрібно.
|
||||
|
||||
Враховуючи простоту Flask, він здавався хорошим підходом для створення API. Наступним, що знайшов, був «Django REST Framework» для Flask.
|
||||
|
||||
!!! Переглянте "Надихнуло **FastAPI** на"
|
||||
Бути мікрофреймоворком. Зробити легким комбінування та поєднання необхідних інструментів та частин.
|
||||
|
||||
Мати просту та легку у використанні систему маршрутизації.
|
||||
|
||||
|
||||
### <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a>
|
||||
|
||||
**FastAPI** насправді не є альтернативою **Requests**. Сфера їх застосування дуже різна.
|
||||
|
||||
Насправді цілком звична річ використовувати Requests *всередині* програми FastAPI.
|
||||
|
||||
Але все ж FastAPI черпав натхнення з Requests.
|
||||
|
||||
**Requests** — це бібліотека для *взаємодії* з API (як клієнт), а **FastAPI** — це бібліотека для *створення* API (як сервер).
|
||||
|
||||
Вони більш-менш знаходяться на протилежних кінцях, доповнюючи одна одну.
|
||||
|
||||
Requests мають дуже простий та інтуїтивно зрозумілий дизайн, дуже простий у використанні, з розумними параметрами за замовчуванням. Але в той же час він дуже потужний і налаштовується.
|
||||
|
||||
Ось чому, як сказано на офіційному сайті:
|
||||
|
||||
> Requests є одним із найбільш завантажуваних пакетів Python усіх часів
|
||||
|
||||
Використовувати його дуже просто. Наприклад, щоб виконати запит `GET`, ви повинні написати:
|
||||
|
||||
```Python
|
||||
response = requests.get("http://example.com/some/url")
|
||||
```
|
||||
|
||||
Відповідна операція *роуту* API FastAPI може виглядати так:
|
||||
|
||||
```Python hl_lines="1"
|
||||
@app.get("/some/url")
|
||||
def read_url():
|
||||
return {"message": "Hello World"}
|
||||
```
|
||||
|
||||
Зверніть увагу на схожість у `requests.get(...)` і `@app.get(...)`.
|
||||
|
||||
!!! Перегляньте "Надихнуло **FastAPI** на"
|
||||
* Майте простий та інтуїтивно зрозумілий API.
|
||||
* Використовуйте імена (операції) методів HTTP безпосередньо, простим та інтуїтивно зрозумілим способом.
|
||||
* Розумні параметри за замовчуванням, але потужні налаштування.
|
||||
|
||||
|
||||
### <a href="https://swagger.io/" class="external-link" target="_blank">Swagger</a> / <a href="https://github.com/OAI /OpenAPI-Specification/" class="external-link" target="_blank">OpenAPI</a>
|
||||
|
||||
Головною функцією, яку я хотів від Django REST Framework, була автоматична API документація.
|
||||
|
||||
Потім я виявив, що існує стандарт для документування API з використанням JSON (або YAML, розширення JSON) під назвою Swagger.
|
||||
|
||||
І вже був створений веб-інтерфейс користувача для Swagger API. Отже, можливість генерувати документацію Swagger для API дозволить використовувати цей веб-інтерфейс автоматично.
|
||||
|
||||
У якийсь момент Swagger було передано Linux Foundation, щоб перейменувати його на OpenAPI.
|
||||
|
||||
Тому, коли говорять про версію 2.0, прийнято говорити «Swagger», а про версію 3+ «OpenAPI».
|
||||
|
||||
!!! Перегляньте "Надихнуло **FastAPI** на"
|
||||
Прийняти і використовувати відкритий стандарт для специфікацій API замість спеціальної схеми.
|
||||
|
||||
Інтегрувати інструменти інтерфейсу на основі стандартів:
|
||||
|
||||
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Інтерфейс Swagger</a>
|
||||
* <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>
|
||||
|
||||
Ці два було обрано через те, що вони досить популярні та стабільні, але, виконавши швидкий пошук, ви можете знайти десятки додаткових альтернативних інтерфейсів для OpenAPI (які можна використовувати з **FastAPI**).
|
||||
|
||||
### Фреймворки REST для Flask
|
||||
|
||||
Існує кілька фреймворків Flask REST, але, витративши час і роботу на їх дослідження, я виявив, що багато з них припинено або залишено, з кількома постійними проблемами, які зробили їх непридатними.
|
||||
|
||||
### <a href="https://marshmallow.readthedocs.io/en/stable/" class="external-link" target="_blank">Marshmallow</a>
|
||||
|
||||
Однією з головних функцій, необхідних для систем API, є "<abbr title="також звана marshalling, conversion">серіалізація</abbr>", яка бере дані з коду (Python) і перетворює їх на щось, що можна надіслати через мережу. Наприклад, перетворення об’єкта, що містить дані з бази даних, на об’єкт JSON. Перетворення об’єктів `datetime` на строки тощо.
|
||||
|
||||
Іншою важливою функцією, необхідною для API, є перевірка даних, яка забезпечує дійсність даних за певними параметрами. Наприклад, що деяке поле є `int`, а не деяка випадкова строка. Це особливо корисно для вхідних даних.
|
||||
|
||||
Без системи перевірки даних вам довелося б виконувати всі перевірки вручну, у коді.
|
||||
|
||||
Marshmallow створено для забезпечення цих функцій. Це чудова бібліотека, і я часто нею користувався раніше.
|
||||
|
||||
Але він був створений до того, як існували підказки типу Python. Отже, щоб визначити кожну <abbr title="визначення того, як дані повинні бути сформовані">схему</abbr>, вам потрібно використовувати спеціальні утиліти та класи, надані Marshmallow.
|
||||
|
||||
!!! Перегляньте "Надихнуло **FastAPI** на"
|
||||
Використовувати код для автоматичного визначення "схем", які надають типи даних і перевірку.
|
||||
|
||||
### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a>
|
||||
|
||||
Іншою важливою функцією, необхідною для API, є <abbr title="читання та перетворення даних Python">аналіз</abbr> даних із вхідних запитів.
|
||||
|
||||
Webargs — це інструмент, створений, щоб забезпечити це поверх кількох фреймворків, включаючи Flask.
|
||||
|
||||
Він використовує Marshmallow в основі для перевірки даних. І створений тими ж розробниками.
|
||||
|
||||
Це чудовий інструмент, і я також часто використовував його, перш ніж створити **FastAPI**.
|
||||
|
||||
!!! Інформація
|
||||
Webargs був створений тими ж розробниками Marshmallow.
|
||||
|
||||
!!! Перегляньте "Надихнуло **FastAPI** на"
|
||||
Мати автоматичну перевірку даних вхідного запиту.
|
||||
|
||||
### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a>
|
||||
|
||||
Marshmallow і Webargs забезпечують перевірку, аналіз і серіалізацію як плагіни.
|
||||
|
||||
Але документація досі відсутня. Потім було створено APISpec.
|
||||
|
||||
Це плагін для багатьох фреймворків (також є плагін для Starlette).
|
||||
|
||||
Принцип роботи полягає в тому, що ви пишете визначення схеми, використовуючи формат YAML, у docstring кожної функції, що обробляє маршрут.
|
||||
|
||||
І він генерує схеми OpenAPI.
|
||||
|
||||
Так це працює у Flask, Starlette, Responder тощо.
|
||||
|
||||
Але потім ми знову маємо проблему наявності мікросинтаксису всередині Python строки (великий YAML).
|
||||
|
||||
Редактор тут нічим не може допомогти. І якщо ми змінимо параметри чи схеми Marshmallow і забудемо також змінити цю строку документа YAML, згенерована схема буде застарілою.
|
||||
|
||||
!!! Інформація
|
||||
APISpec був створений тими ж розробниками Marshmallow.
|
||||
|
||||
|
||||
!!! Перегляньте "Надихнуло **FastAPI** на"
|
||||
Підтримувати відкритий стандарт API, OpenAPI.
|
||||
|
||||
### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a>
|
||||
|
||||
Це плагін Flask, який об’єднує Webargs, Marshmallow і APISpec.
|
||||
|
||||
Він використовує інформацію з Webargs і Marshmallow для автоматичного створення схем OpenAPI за допомогою APISpec.
|
||||
|
||||
Це чудовий інструмент, дуже недооцінений. Він має бути набагато популярнішим, ніж багато плагінів Flask. Це може бути пов’язано з тим, що його документація надто стисла й абстрактна.
|
||||
|
||||
Це вирішило необхідність писати YAML (інший синтаксис) всередині рядків документів Python.
|
||||
|
||||
Ця комбінація Flask, Flask-apispec із Marshmallow і Webargs була моїм улюбленим бекенд-стеком до створення **FastAPI**.
|
||||
|
||||
Їі використання призвело до створення кількох генераторів повного стека Flask. Це основний стек, який я (та кілька зовнішніх команд) використовував досі:
|
||||
|
||||
* <a href="https://github.com/tiangolo/full-stack" class="external-link" target="_blank">https://github.com/tiangolo/full-stack</a>
|
||||
* <a href="https://github.com/tiangolo/full-stack-flask-couchbase" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchbase</a>
|
||||
* <a href="https://github.com/tiangolo/full-stack-flask-couchdb" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchdb</a>
|
||||
|
||||
І ці самі генератори повного стеку були основою [**FastAPI** генераторів проектів](project-generation.md){.internal-link target=_blank}.
|
||||
|
||||
!!! Інформація
|
||||
Flask-apispec був створений тими ж розробниками Marshmallow.
|
||||
|
||||
!!! Перегляньте "Надихнуло **FastAPI** на"
|
||||
Створення схеми OpenAPI автоматично з того самого коду, який визначає серіалізацію та перевірку.
|
||||
|
||||
### <a href="https://nestjs.com/" class="external-link" target="_blank">NestJS</a> (та <a href="https://angular.io/ " class="external-link" target="_blank">Angular</a>)
|
||||
|
||||
Це навіть не Python, NestJS — це фреймворк NodeJS JavaScript (TypeScript), натхненний Angular.
|
||||
|
||||
Це досягає чогось подібного до того, що можна зробити з Flask-apispec.
|
||||
|
||||
Він має інтегровану систему впровадження залежностей, натхненну Angular two. Він потребує попередньої реєстрації «injectables» (як і всі інші системи впровадження залежностей, які я знаю), тому це збільшує багатослівність та повторення коду.
|
||||
|
||||
Оскільки параметри описані за допомогою типів TypeScript (подібно до підказок типу Python), підтримка редактора досить хороша.
|
||||
|
||||
Але оскільки дані TypeScript не зберігаються після компіляції в JavaScript, вони не можуть покладатися на типи для визначення перевірки, серіалізації та документації одночасно. Через це та деякі дизайнерські рішення, щоб отримати перевірку, серіалізацію та автоматичну генерацію схеми, потрібно додати декоратори в багатьох місцях. Таким чином код стає досить багатослівним.
|
||||
|
||||
Він не дуже добре обробляє вкладені моделі. Отже, якщо тіло JSON у запиті є об’єктом JSON із внутрішніми полями, які, у свою чергу, є вкладеними об’єктами JSON, його неможливо належним чином задокументувати та перевірити.
|
||||
|
||||
!!! Перегляньте "Надихнуло **FastAPI** на"
|
||||
Використовувати типи Python, щоб мати чудову підтримку редактора.
|
||||
|
||||
Мати потужну систему впровадження залежностей. Знайдіть спосіб звести до мінімуму повторення коду.
|
||||
|
||||
### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a>
|
||||
|
||||
Це був один із перших надзвичайно швидких фреймворків Python на основі `asyncio`. Він був дуже схожий на Flask.
|
||||
|
||||
!!! Примітка "Технічні деталі"
|
||||
Він використовував <a href="https://github.com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a> замість стандартного циклу Python `asyncio`. Ось що зробило його таким швидким.
|
||||
|
||||
Це явно надихнуло Uvicorn і Starlette, які зараз швидші за Sanic у відкритих тестах.
|
||||
|
||||
!!! Перегляньте "Надихнуло **FastAPI** на"
|
||||
Знайти спосіб отримати божевільну продуктивність.
|
||||
|
||||
Ось чому **FastAPI** базується на Starlette, оскільки це найшвидша доступна структура (перевірена тестами сторонніх розробників).
|
||||
|
||||
### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a>
|
||||
|
||||
Falcon — ще один високопродуктивний фреймворк Python, він розроблений як мінімальний і працює як основа інших фреймворків, таких як Hug.
|
||||
|
||||
Він розроблений таким чином, щоб мати функції, які отримують два параметри, один «запит» і один «відповідь». Потім ви «читаєте» частини запиту та «записуєте» частини у відповідь. Через такий дизайн неможливо оголосити параметри запиту та тіла за допомогою стандартних підказок типу Python як параметри функції.
|
||||
|
||||
Таким чином, перевірка даних, серіалізація та документація повинні виконуватися в коді, а не автоматично. Або вони повинні бути реалізовані як фреймворк поверх Falcon, як Hug. Така сама відмінність спостерігається в інших фреймворках, натхненних дизайном Falcon, що мають один об’єкт запиту та один об’єкт відповіді як параметри.
|
||||
|
||||
!!! Перегляньте "Надихнуло **FastAPI** на"
|
||||
Знайти способи отримати чудову продуктивність.
|
||||
|
||||
Разом із Hug (оскільки Hug базується на Falcon) надихнув **FastAPI** оголосити параметр `response` у функціях.
|
||||
|
||||
Хоча у FastAPI це необов’язково, і використовується в основному для встановлення заголовків, файлів cookie та альтернативних кодів стану.
|
||||
|
||||
### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a>
|
||||
|
||||
Я відкрив для себе Molten на перших етапах створення **FastAPI**. І він має досить схожі ідеї:
|
||||
|
||||
* Базується на підказках типу Python.
|
||||
* Перевірка та документація цих типів.
|
||||
* Система впровадження залежностей.
|
||||
|
||||
Він не використовує перевірку даних, серіалізацію та бібліотеку документації сторонніх розробників, як Pydantic, він має свою власну. Таким чином, ці визначення типів даних не можна було б використовувати повторно так легко.
|
||||
|
||||
Це вимагає трохи більш докладних конфігурацій. І оскільки він заснований на WSGI (замість ASGI), він не призначений для використання високопродуктивних інструментів, таких як Uvicorn, Starlette і Sanic.
|
||||
|
||||
Система впровадження залежностей вимагає попередньої реєстрації залежностей, і залежності вирішуються на основі оголошених типів. Отже, неможливо оголосити більше ніж один «компонент», який надає певний тип.
|
||||
|
||||
Маршрути оголошуються в одному місці з використанням функцій, оголошених в інших місцях (замість використання декораторів, які можна розмістити безпосередньо поверх функції, яка обробляє кінцеву точку). Це ближче до того, як це робить Django, ніж до Flask (і Starlette). Він розділяє в коді речі, які відносно тісно пов’язані.
|
||||
|
||||
!!! Перегляньте "Надихнуло **FastAPI** на"
|
||||
Визначити додаткові перевірки для типів даних, використовуючи значення "за замовчуванням" атрибутів моделі. Це покращує підтримку редактора, а раніше вона була недоступна в Pydantic.
|
||||
|
||||
Це фактично надихнуло оновити частини Pydantic, щоб підтримувати той самий стиль оголошення перевірки (всі ці функції вже доступні в Pydantic).
|
||||
|
||||
### <a href="https://www.hug.rest/" class="external-link" target="_blank">Hug</a>
|
||||
|
||||
Hug був одним із перших фреймворків, який реалізував оголошення типів параметрів API за допомогою підказок типу Python. Це була чудова ідея, яка надихнула інші інструменти зробити те саме.
|
||||
|
||||
Він використовував спеціальні типи у своїх оголошеннях замість стандартних типів Python, але це все одно був величезний крок вперед.
|
||||
|
||||
Це також був один із перших фреймворків, який генерував спеціальну схему, що оголошувала весь API у JSON.
|
||||
|
||||
Він не базувався на таких стандартах, як OpenAPI та JSON Schema. Тому було б непросто інтегрувати його з іншими інструментами, як-от Swagger UI. Але знову ж таки, це була дуже інноваційна ідея.
|
||||
|
||||
Він має цікаву незвичайну функцію: використовуючи ту саму структуру, можна створювати API, а також CLI.
|
||||
|
||||
Оскільки він заснований на попередньому стандарті для синхронних веб-фреймворків Python (WSGI), він не може працювати з Websockets та іншими речами, хоча він також має високу продуктивність.
|
||||
|
||||
!!! Інформація
|
||||
Hug створив Тімоті Крослі, той самий творець <a href="https://github.com/timothycrosley/isort" class="external-link" target="_blank">`isort`</a>, чудовий інструмент для автоматичного сортування імпорту у файлах Python.
|
||||
|
||||
!!! Перегляньте "Надихнуло **FastAPI** на"
|
||||
Hug надихнув частину APIStar і був одним із найбільш перспективних інструментів, поряд із APIStar.
|
||||
|
||||
Hug надихнув **FastAPI** на використання підказок типу Python для оголошення параметрів і автоматичного створення схеми, що визначає API.
|
||||
|
||||
Hug надихнув **FastAPI** оголосити параметр `response` у функціях для встановлення заголовків і файлів cookie.
|
||||
|
||||
### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (<= 0,5)
|
||||
|
||||
Безпосередньо перед тим, як вирішити створити **FastAPI**, я знайшов сервер **APIStar**. Він мав майже все, що я шукав, і мав чудовий дизайн.
|
||||
|
||||
Це була одна з перших реалізацій фреймворку, що використовує підказки типу Python для оголошення параметрів і запитів, яку я коли-небудь бачив (до NestJS і Molten). Я знайшов його більш-менш одночасно з Hug. Але APIStar використовував стандарт OpenAPI.
|
||||
|
||||
Він мав автоматичну перевірку даних, серіалізацію даних і генерацію схеми OpenAPI на основі підказок того самого типу в кількох місцях.
|
||||
|
||||
Визначення схеми тіла не використовували ті самі підказки типу Python, як Pydantic, воно було трохи схоже на Marshmallow, тому підтримка редактора була б не такою хорошою, але все ж APIStar був найкращим доступним варіантом.
|
||||
|
||||
Він мав найкращі показники продуктивності на той час (перевершив лише Starlette).
|
||||
|
||||
Спочатку він не мав автоматичного веб-інтерфейсу документації API, але я знав, що можу додати до нього інтерфейс користувача Swagger.
|
||||
|
||||
Він мав систему введення залежностей. Він вимагав попередньої реєстрації компонентів, як і інші інструменти, розглянуті вище. Але все одно це була чудова функція.
|
||||
|
||||
Я ніколи не міг використовувати його в повноцінному проекті, оскільки він не мав інтеграції безпеки, тому я не міг замінити всі функції, які мав, генераторами повного стеку на основі Flask-apispec. У моїх невиконаних проектах я мав створити запит на вилучення, додавши цю функцію.
|
||||
|
||||
Але потім фокус проекту змінився.
|
||||
|
||||
Це вже не був веб-фреймворк API, оскільки творцю потрібно було зосередитися на Starlette.
|
||||
|
||||
Тепер APIStar — це набір інструментів для перевірки специфікацій OpenAPI, а не веб-фреймворк.
|
||||
|
||||
!!! Інформація
|
||||
APIStar створив Том Крісті. Той самий хлопець, який створив:
|
||||
|
||||
* Django REST Framework
|
||||
* Starlette (на якому базується **FastAPI**)
|
||||
* Uvicorn (використовується Starlette і **FastAPI**)
|
||||
|
||||
!!! Перегляньте "Надихнуло **FastAPI** на"
|
||||
Існувати.
|
||||
|
||||
Ідею оголошення кількох речей (перевірки даних, серіалізації та документації) за допомогою тих самих типів Python, які в той же час забезпечували чудову підтримку редактора, я вважав геніальною ідеєю.
|
||||
|
||||
І після тривалого пошуку подібної структури та тестування багатьох різних альтернатив, APIStar став найкращим доступним варіантом.
|
||||
|
||||
Потім APIStar перестав існувати як сервер, і було створено Starlette, який став новою кращою основою для такої системи. Це стало останнім джерелом натхнення для створення **FastAPI**. Я вважаю **FastAPI** «духовним спадкоємцем» APIStar, удосконалюючи та розширюючи функції, систему введення тексту та інші частини на основі досвіду, отриманого від усіх цих попередніх інструментів.
|
||||
|
||||
## Використовується **FastAPI**
|
||||
|
||||
### <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a>
|
||||
|
||||
Pydantic — це бібліотека для визначення перевірки даних, серіалізації та документації (за допомогою схеми JSON) на основі підказок типу Python.
|
||||
|
||||
Це робить його надзвичайно інтуїтивним.
|
||||
|
||||
Його можна порівняти з Marshmallow. Хоча він швидший за Marshmallow у тестах. Оскільки він базується на тих самих підказках типу Python, підтримка редактора чудова.
|
||||
|
||||
!!! Перегляньте "**FastAPI** використовує його для"
|
||||
Виконання перевірки всіх даних, серіалізації даних і автоматичної документацію моделі (на основі схеми JSON).
|
||||
|
||||
Потім **FastAPI** бере ці дані схеми JSON і розміщує їх у OpenAPI, окремо від усіх інших речей, які він робить.
|
||||
|
||||
### <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>
|
||||
|
||||
Starlette — це легкий фреймворк/набір інструментів <abbr title="The new standard for build asynchronous Python web">ASGI</abbr>, який ідеально підходить для створення високопродуктивних asyncio сервісів.
|
||||
|
||||
Він дуже простий та інтуїтивно зрозумілий. Його розроблено таким чином, щоб його можна було легко розширювати та мати модульні компоненти.
|
||||
|
||||
Він має:
|
||||
|
||||
* Серйозно вражаючу продуктивність.
|
||||
* Підтримку WebSocket.
|
||||
* Фонові завдання в процесі.
|
||||
* Події запуску та завершення роботи.
|
||||
* Тестового клієнта, побудований на HTTPX.
|
||||
* CORS, GZip, статичні файли, потокові відповіді.
|
||||
* Підтримку сеансів і файлів cookie.
|
||||
* 100% покриття тестом.
|
||||
* 100% анотовану кодову базу.
|
||||
* Кілька жорстких залежностей.
|
||||
|
||||
Starlette наразі є найшвидшим фреймворком Python із перевірених. Перевершує лише Uvicorn, який є не фреймворком, а сервером.
|
||||
|
||||
Starlette надає всі основні функції веб-мікрофреймворку.
|
||||
|
||||
Але він не забезпечує автоматичної перевірки даних, серіалізації чи документації.
|
||||
|
||||
Це одна з головних речей, які **FastAPI** додає зверху, все на основі підказок типу Python (з використанням Pydantic). Це, а також система впровадження залежностей, утиліти безпеки, створення схеми OpenAPI тощо.
|
||||
|
||||
!!! Примітка "Технічні деталі"
|
||||
ASGI — це новий «стандарт», який розробляється членами основної команди Django. Це ще не «стандарт Python» (PEP), хоча вони в процесі цього.
|
||||
|
||||
Тим не менш, він уже використовується як «стандарт» кількома інструментами. Це значно покращує сумісність, оскільки ви можете переключити Uvicorn на будь-який інший сервер ASGI (наприклад, Daphne або Hypercorn), або ви можете додати інструменти, сумісні з ASGI, як-от `python-socketio`.
|
||||
|
||||
!!! Перегляньте "**FastAPI** використовує його для"
|
||||
Керування всіма основними веб-частинами. Додавання функцій зверху.
|
||||
|
||||
Сам клас `FastAPI` безпосередньо успадковує клас `Starlette`.
|
||||
|
||||
Отже, усе, що ви можете робити зі Starlette, ви можете робити це безпосередньо за допомогою **FastAPI**, оскільки це, по суті, Starlette на стероїдах.
|
||||
|
||||
### <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>
|
||||
|
||||
Uvicorn — це блискавичний сервер ASGI, побудований на uvloop і httptools.
|
||||
|
||||
Це не веб-фреймворк, а сервер. Наприклад, він не надає інструментів для маршрутизації. Це те, що фреймворк на кшталт Starlette (або **FastAPI**) забезпечить поверх нього.
|
||||
|
||||
Це рекомендований сервер для Starlette і **FastAPI**.
|
||||
|
||||
!!! Перегляньте "**FastAPI** рекомендує це як"
|
||||
Основний веб-сервер для запуску програм **FastAPI**.
|
||||
|
||||
Ви можете поєднати його з Gunicorn, щоб мати асинхронний багатопроцесний сервер.
|
||||
|
||||
Додаткову інформацію див. у розділі [Розгортання](deployment/index.md){.internal-link target=_blank}.
|
||||
|
||||
## Орієнтири та швидкість
|
||||
|
||||
Щоб зрозуміти, порівняти та побачити різницю між Uvicorn, Starlette і FastAPI, перегляньте розділ про [Бенчмарки](benchmarks.md){.internal-link target=_blank}.
|
||||
448
docs/uk/docs/python-types.md
Normal file
448
docs/uk/docs/python-types.md
Normal file
@@ -0,0 +1,448 @@
|
||||
# Вступ до типів Python
|
||||
|
||||
Python підтримує додаткові "підказки типу" ("type hints") (також звані "анотаціями типу" ("type annotations")).
|
||||
|
||||
Ці **"type hints"** є спеціальним синтаксисом, що дозволяє оголошувати <abbr title="наприклад: str, int, float, bool">тип</abbr> змінної.
|
||||
|
||||
За допомогою оголошення типів для ваших змінних, редактори та інструменти можуть надати вам кращу підтримку.
|
||||
|
||||
Це просто **швидкий посібник / нагадування** про анотації типів у Python. Він покриває лише мінімум, необхідний щоб використовувати їх з **FastAPI**... що насправді дуже мало.
|
||||
|
||||
**FastAPI** повністю базується на цих анотаціях типів, вони дають йому багато переваг.
|
||||
|
||||
Але навіть якщо ви ніколи не використаєте **FastAPI**, вам буде корисно дізнатись трохи про них.
|
||||
|
||||
!!! note
|
||||
Якщо ви експерт у Python і ви вже знаєте усе про анотації типів - перейдіть до наступного розділу.
|
||||
|
||||
## Мотивація
|
||||
|
||||
Давайте почнемо з простого прикладу:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/python_types/tutorial001.py!}
|
||||
```
|
||||
|
||||
Виклик цієї програми виводить:
|
||||
|
||||
```
|
||||
John Doe
|
||||
```
|
||||
|
||||
Функція виконує наступне:
|
||||
|
||||
* Бере `first_name` та `last_name`.
|
||||
* Конвертує кожну літеру кожного слова у верхній регістр за допомогою `title()`.
|
||||
* <abbr title="З’єднує їх, як одне ціле. З вмістом один за одним.">Конкатенує</abbr> їх разом із пробілом по середині.
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!../../../docs_src/python_types/tutorial001.py!}
|
||||
```
|
||||
|
||||
### Редагуйте це
|
||||
|
||||
Це дуже проста програма.
|
||||
|
||||
Але тепер уявіть, що ви писали це з нуля.
|
||||
|
||||
У певний момент ви розпочали б визначення функції, у вас були б готові параметри...
|
||||
|
||||
Але тоді вам потрібно викликати "той метод, який переводить першу літеру у верхній регістр".
|
||||
|
||||
Це буде `upper`? Чи `uppercase`? `first_uppercase`? `capitalize`?
|
||||
|
||||
Тоді ви спробуєте давнього друга програміста - автозаповнення редактора коду.
|
||||
|
||||
Ви надрукуєте перший параметр функції, `first_name`, тоді крапку (`.`), а тоді натиснете `Ctrl+Space`, щоб запустити автозаповнення.
|
||||
|
||||
Але, на жаль, ви не отримаєте нічого корисного:
|
||||
|
||||
<img src="/img/python-types/image01.png">
|
||||
|
||||
### Додайте типи
|
||||
|
||||
Давайте змінимо один рядок з попередньої версії.
|
||||
|
||||
Ми змінимо саме цей фрагмент, параметри функції, з:
|
||||
|
||||
```Python
|
||||
first_name, last_name
|
||||
```
|
||||
|
||||
на:
|
||||
|
||||
```Python
|
||||
first_name: str, last_name: str
|
||||
```
|
||||
|
||||
Ось і все.
|
||||
|
||||
Це "type hints":
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/python_types/tutorial002.py!}
|
||||
```
|
||||
|
||||
Це не те саме, що оголошення значень за замовчуванням, як це було б з:
|
||||
|
||||
```Python
|
||||
first_name="john", last_name="doe"
|
||||
```
|
||||
|
||||
Це зовсім інше.
|
||||
|
||||
Ми використовуємо двокрапку (`:`), не дорівнює (`=`).
|
||||
|
||||
І додавання анотації типу зазвичай не змінює того, що сталось би без них.
|
||||
|
||||
Але тепер, уявіть що ви посеред процесу створення функції, але з анотаціями типів.
|
||||
|
||||
В цей же момент, ви спробуєте викликати автозаповнення з допомогою `Ctrl+Space` і побачите:
|
||||
|
||||
<img src="/img/python-types/image02.png">
|
||||
|
||||
Разом з цим, ви можете прокручувати, переглядати опції, допоки ви не знайдете одну, що звучить схоже:
|
||||
|
||||
<img src="/img/python-types/image03.png">
|
||||
|
||||
## Більше мотивації
|
||||
|
||||
Перевірте цю функцію, вона вже має анотацію типу:
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/python_types/tutorial003.py!}
|
||||
```
|
||||
|
||||
Оскільки редактор знає типи змінних, ви не тільки отримаєте автозаповнення, ви також отримаєте перевірку помилок:
|
||||
|
||||
<img src="/img/python-types/image04.png">
|
||||
|
||||
Тепер ви знаєте, щоб виправити це, вам потрібно перетворити `age` у строку з допомогою `str(age)`:
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!../../../docs_src/python_types/tutorial004.py!}
|
||||
```
|
||||
|
||||
## Оголошення типів
|
||||
|
||||
Щойно ви побачили основне місце для оголошення анотацій типу. Як параметри функції.
|
||||
|
||||
Це також основне місце, де ви б їх використовували у **FastAPI**.
|
||||
|
||||
### Прості типи
|
||||
|
||||
Ви можете оголошувати усі стандартні типи у Python, не тільки `str`.
|
||||
|
||||
Ви можете використовувати, наприклад:
|
||||
|
||||
* `int`
|
||||
* `float`
|
||||
* `bool`
|
||||
* `bytes`
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/python_types/tutorial005.py!}
|
||||
```
|
||||
|
||||
### Generic-типи з параметрами типів
|
||||
|
||||
Існують деякі структури даних, які можуть містити інші значення, наприклад `dict`, `list`, `set` та `tuple`. І внутрішні значення також можуть мати свій тип.
|
||||
|
||||
Ці типи, які мають внутрішні типи, називаються "**generic**" типами. І оголосити їх можна навіть із внутрішніми типами.
|
||||
|
||||
Щоб оголосити ці типи та внутрішні типи, ви можете використовувати стандартний модуль Python `typing`. Він існує спеціально для підтримки анотацій типів.
|
||||
|
||||
#### Новіші версії Python
|
||||
|
||||
Синтаксис із використанням `typing` **сумісний** з усіма версіями, від Python 3.6 до останніх, включаючи Python 3.9, Python 3.10 тощо.
|
||||
|
||||
У міру розвитку Python **новіші версії** мають покращену підтримку анотацій типів і в багатьох випадках вам навіть не потрібно буде імпортувати та використовувати модуль `typing` для оголошення анотацій типу.
|
||||
|
||||
Якщо ви можете вибрати новішу версію Python для свого проекту, ви зможете скористатися цією додатковою простотою. Дивіться кілька прикладів нижче.
|
||||
|
||||
#### List (список)
|
||||
|
||||
Наприклад, давайте визначимо змінну, яка буде `list` із `str`.
|
||||
|
||||
=== "Python 3.6 і вище"
|
||||
|
||||
З модуля `typing`, імпортуємо `List` (з великої літери `L`):
|
||||
|
||||
``` Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
|
||||
Оголосимо змінну з тим самим синтаксисом двокрапки (`:`).
|
||||
|
||||
Як тип вкажемо `List`, який ви імпортували з `typing`.
|
||||
|
||||
Оскільки список є типом, який містить деякі внутрішні типи, ви поміщаєте їх у квадратні дужки:
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 і вище"
|
||||
|
||||
Оголосимо змінну з тим самим синтаксисом двокрапки (`:`).
|
||||
|
||||
Як тип вкажемо `list`.
|
||||
|
||||
Оскільки список є типом, який містить деякі внутрішні типи, ви поміщаєте їх у квадратні дужки:
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial006_py39.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
Ці внутрішні типи в квадратних дужках називаються "параметрами типу".
|
||||
|
||||
У цьому випадку, `str` це параметр типу переданий у `List` (або `list` у Python 3.9 і вище).
|
||||
|
||||
Це означає: "змінна `items` це `list`, і кожен з елементів у цьому списку - `str`".
|
||||
|
||||
!!! tip
|
||||
Якщо ви використовуєте Python 3.9 і вище, вам не потрібно імпортувати `List` з `typing`, ви можете використовувати натомість тип `list`.
|
||||
|
||||
Зробивши це, ваш редактор може надати підтримку навіть під час обробки елементів зі списку:
|
||||
|
||||
<img src="/img/python-types/image05.png">
|
||||
|
||||
Без типів цього майже неможливо досягти.
|
||||
|
||||
Зверніть увагу, що змінна `item` є одним із елементів у списку `items`.
|
||||
|
||||
І все ж редактор знає, що це `str`, і надає підтримку для цього.
|
||||
|
||||
#### Tuple and Set (кортеж та набір)
|
||||
|
||||
Ви повинні зробити те ж саме, щоб оголосити `tuple` і `set`:
|
||||
|
||||
=== "Python 3.6 і вище"
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial007.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 і вище"
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial007_py39.py!}
|
||||
```
|
||||
|
||||
Це означає:
|
||||
|
||||
* Змінна `items_t` це `tuple` з 3 елементами, `int`, ще `int`, та `str`.
|
||||
* Змінна `items_s` це `set`, і кожен його елемент типу `bytes`.
|
||||
|
||||
#### Dict (словник)
|
||||
|
||||
Щоб оголосити `dict`, вам потрібно передати 2 параметри типу, розділені комами.
|
||||
|
||||
Перший параметр типу для ключа у `dict`.
|
||||
|
||||
Другий параметр типу для значення у `dict`:
|
||||
|
||||
=== "Python 3.6 і вище"
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial008.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 і вище"
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial008_py39.py!}
|
||||
```
|
||||
|
||||
Це означає:
|
||||
|
||||
* Змінна `prices` це `dict`:
|
||||
* Ключі цього `dict` типу `str` (наприклад, назва кожного елементу).
|
||||
* Значення цього `dict` типу `float` (наприклад, ціна кожного елементу).
|
||||
|
||||
#### Union (об'єднання)
|
||||
|
||||
Ви можете оголосити, що змінна може бути будь-яким із **кількох типів**, наприклад, `int` або `str`.
|
||||
|
||||
У Python 3.6 і вище (включаючи Python 3.10) ви можете використовувати тип `Union` з `typing` і вставляти в квадратні дужки можливі типи, які можна прийняти.
|
||||
|
||||
У Python 3.10 також є **альтернативний синтаксис**, у якому ви можете розділити можливі типи за допомогою <abbr title='також називають «побітовим "або" оператором», але це значення тут не актуальне'>вертикальної смуги (`|`)</abbr>.
|
||||
|
||||
=== "Python 3.6 і вище"
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial008b.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 і вище"
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial008b_py310.py!}
|
||||
```
|
||||
|
||||
В обох випадках це означає, що `item` може бути `int` або `str`.
|
||||
|
||||
#### Possibly `None` (Optional)
|
||||
|
||||
Ви можете оголосити, що значення може мати тип, наприклад `str`, але також може бути `None`.
|
||||
|
||||
У Python 3.6 і вище (включаючи Python 3.10) ви можете оголосити його, імпортувавши та використовуючи `Optional` з модуля `typing`.
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../../docs_src/python_types/tutorial009.py!}
|
||||
```
|
||||
|
||||
Використання `Optional[str]` замість просто `str` дозволить редактору допомогти вам виявити помилки, коли ви могли б вважати, що значенням завжди є `str`, хоча насправді воно також може бути `None`.
|
||||
|
||||
`Optional[Something]` насправді є скороченням для `Union[Something, None]`, вони еквівалентні.
|
||||
|
||||
Це також означає, що в Python 3.10 ви можете використовувати `Something | None`:
|
||||
|
||||
=== "Python 3.6 і вище"
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial009.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6 і вище - альтернатива"
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial009b.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 і вище"
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial009_py310.py!}
|
||||
```
|
||||
|
||||
#### Generic типи
|
||||
|
||||
Ці типи, які приймають параметри типу у квадратних дужках, називаються **Generic types** or **Generics**, наприклад:
|
||||
|
||||
=== "Python 3.6 і вище"
|
||||
|
||||
* `List`
|
||||
* `Tuple`
|
||||
* `Set`
|
||||
* `Dict`
|
||||
* `Union`
|
||||
* `Optional`
|
||||
* ...та інші.
|
||||
|
||||
=== "Python 3.9 і вище"
|
||||
|
||||
Ви можете використовувати ті самі вбудовані типи, як generic (з квадратними дужками та типами всередині):
|
||||
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
|
||||
І те саме, що й у Python 3.6, із модуля `typing`:
|
||||
|
||||
* `Union`
|
||||
* `Optional`
|
||||
* ...та інші.
|
||||
|
||||
=== "Python 3.10 і вище"
|
||||
|
||||
Ви можете використовувати ті самі вбудовані типи, як generic (з квадратними дужками та типами всередині):
|
||||
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
|
||||
І те саме, що й у Python 3.6, із модуля `typing`:
|
||||
|
||||
* `Union`
|
||||
* `Optional` (так само як у Python 3.6)
|
||||
* ...та інші.
|
||||
|
||||
У Python 3.10, як альтернатива використанню `Union` та `Optional`, ви можете використовувати <abbr title='також називають «побітовим "або" оператором», але це значення тут не актуальне'>вертикальну смугу (`|`)</abbr> щоб оголосити об'єднання типів.
|
||||
|
||||
### Класи як типи
|
||||
|
||||
Ви також можете оголосити клас як тип змінної.
|
||||
|
||||
Скажімо, у вас є клас `Person` з імʼям:
|
||||
|
||||
```Python hl_lines="1-3"
|
||||
{!../../../docs_src/python_types/tutorial010.py!}
|
||||
```
|
||||
|
||||
Потім ви можете оголосити змінну типу `Person`:
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/python_types/tutorial010.py!}
|
||||
```
|
||||
|
||||
І знову ж таки, ви отримуєте всю підтримку редактора:
|
||||
|
||||
<img src="/img/python-types/image06.png">
|
||||
|
||||
## Pydantic моделі
|
||||
|
||||
<a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> це бібліотека Python для валідації даних.
|
||||
|
||||
Ви оголошуєте «форму» даних як класи з атрибутами.
|
||||
|
||||
І кожен атрибут має тип.
|
||||
|
||||
Потім ви створюєте екземпляр цього класу з деякими значеннями, і він перевірить ці значення, перетворить їх у відповідний тип (якщо є потреба) і надасть вам об’єкт з усіма даними.
|
||||
|
||||
І ви отримуєте всю підтримку редактора з цим отриманим об’єктом.
|
||||
|
||||
Приклад з документації Pydantic:
|
||||
|
||||
=== "Python 3.6 і вище"
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/python_types/tutorial011.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 і вище"
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/python_types/tutorial011_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 і вище"
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/python_types/tutorial011_py310.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
Щоб дізнатись більше про <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic, перегляньте його документацію</a>.
|
||||
|
||||
**FastAPI** повністю базується на Pydantic.
|
||||
|
||||
Ви побачите набагато більше цього всього на практиці в [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}.
|
||||
|
||||
## Анотації типів у **FastAPI**
|
||||
|
||||
**FastAPI** використовує ці підказки для виконання кількох речей.
|
||||
|
||||
З **FastAPI** ви оголошуєте параметри з підказками типу, і отримуєте:
|
||||
|
||||
* **Підтримку редактора**.
|
||||
* **Перевірку типів**.
|
||||
|
||||
...і **FastAPI** використовує ті самі оголошення для:
|
||||
|
||||
* **Визначення вимог**: з параметрів шляху запиту, параметрів запиту, заголовків, тіл, залежностей тощо.
|
||||
* **Перетворення даних**: із запиту в необхідний тип.
|
||||
* **Перевірка даних**: що надходять від кожного запиту:
|
||||
* Генерування **автоматичних помилок**, що повертаються клієнту, коли дані недійсні.
|
||||
* **Документування** API за допомогою OpenAPI:
|
||||
* який потім використовується для автоматичної інтерактивної документації користувальницьких інтерфейсів.
|
||||
|
||||
Все це може здатися абстрактним. Не хвилюйтеся. Ви побачите все це в дії в [Туторіал - Посібник користувача](tutorial/index.md){.internal-link target=_blank}.
|
||||
|
||||
Важливо те, що за допомогою стандартних типів Python в одному місці (замість того, щоб додавати більше класів, декораторів тощо), **FastAPI** зробить багато роботи за вас.
|
||||
|
||||
!!! info
|
||||
Якщо ви вже пройшли весь навчальний посібник і повернулися, щоб дізнатися більше про типи, ось хороший ресурс <a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">"шпаргалка" від `mypy`</a>.
|
||||
42
docs/uk/docs/tutorial/encoder.md
Normal file
42
docs/uk/docs/tutorial/encoder.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# JSON Compatible Encoder
|
||||
|
||||
Існують випадки, коли вам може знадобитися перетворити тип даних (наприклад, модель Pydantic) в щось сумісне з JSON (наприклад, `dict`, `list`, і т. д.).
|
||||
|
||||
Наприклад, якщо вам потрібно зберегти це в базі даних.
|
||||
|
||||
Для цього, **FastAPI** надає `jsonable_encoder()` функцію.
|
||||
|
||||
## Використання `jsonable_encoder`
|
||||
|
||||
Давайте уявимо, що у вас є база даних `fake_db`, яка приймає лише дані, сумісні з JSON.
|
||||
|
||||
Наприклад, вона не приймає об'єкти типу `datetime`, оскільки вони не сумісні з JSON.
|
||||
|
||||
Отже, об'єкт типу `datetime` потрібно перетворити в рядок `str`, який містить дані в <a href="https://en.wikipedia.org/wiki/ISO_8601" class="external-link" target="_blank">ISO форматі</a>.
|
||||
|
||||
Тим самим способом ця база даних не прийматиме об'єкт типу Pydantic model (об'єкт з атрибутами), а лише `dict`.
|
||||
|
||||
Ви можете використовувати `jsonable_encoder` для цього.
|
||||
|
||||
Вона приймає об'єкт, такий як Pydantic model, і повертає його версію, сумісну з JSON:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="4 21"
|
||||
{!> ../../../docs_src/encoder/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="5 22"
|
||||
{!> ../../../docs_src/encoder/tutorial001.py!}
|
||||
```
|
||||
|
||||
У цьому прикладі вона конвертує Pydantic model у `dict`, а `datetime` у `str`.
|
||||
|
||||
Результат виклику цієї функції - це щось, що можна кодувати з використанням стандарту Python <a href="https://docs.python.org/3/library/json.html#json.dumps" class="external-link" target="_blank">`json.dumps()`</a>.
|
||||
|
||||
Вона не повертає велику строку `str`, яка містить дані у форматі JSON (як строка). Вона повертає стандартну структуру даних Python (наприклад `dict`) із значеннями та підзначеннями, які є сумісними з JSON.
|
||||
|
||||
!!! Примітка
|
||||
`jsonable_encoder` фактично використовується **FastAPI** внутрішньо для перетворення даних. Проте вона корисна в багатьох інших сценаріях.
|
||||
130
docs/uk/docs/tutorial/extra-data-types.md
Normal file
130
docs/uk/docs/tutorial/extra-data-types.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# Додаткові типи даних
|
||||
|
||||
До цього часу, ви використовували загальнопоширені типи даних, такі як:
|
||||
|
||||
* `int`
|
||||
* `float`
|
||||
* `str`
|
||||
* `bool`
|
||||
|
||||
Але можна також використовувати більш складні типи даних.
|
||||
|
||||
І ви все ще матимете ті ж можливості, які були показані до цього:
|
||||
|
||||
* Чудова підтримка редактора.
|
||||
* Конвертація даних з вхідних запитів.
|
||||
* Конвертація даних для відповіді.
|
||||
* Валідація даних.
|
||||
* Автоматична анотація та документація.
|
||||
|
||||
## Інші типи даних
|
||||
|
||||
Ось додаткові типи даних для використання:
|
||||
|
||||
* `UUID`:
|
||||
* Стандартний "Універсальний Унікальний Ідентифікатор", який часто використовується як ідентифікатор у багатьох базах даних та системах.
|
||||
* У запитах та відповідях буде представлений як `str`.
|
||||
* `datetime.datetime`:
|
||||
* Пайтонівський `datetime.datetime`.
|
||||
* У запитах та відповідях буде представлений як `str` в форматі ISO 8601, як: `2008-09-15T15:53:00+05:00`.
|
||||
* `datetime.date`:
|
||||
* Пайтонівський `datetime.date`.
|
||||
* У запитах та відповідях буде представлений як `str` в форматі ISO 8601, як: `2008-09-15`.
|
||||
* `datetime.time`:
|
||||
* Пайтонівський `datetime.time`.
|
||||
* У запитах та відповідях буде представлений як `str` в форматі ISO 8601, як: `14:23:55.003`.
|
||||
* `datetime.timedelta`:
|
||||
* Пайтонівський `datetime.timedelta`.
|
||||
* У запитах та відповідях буде представлений як `float` загальної кількості секунд.
|
||||
* Pydantic також дозволяє представляти це як "ISO 8601 time diff encoding", <a href="https://pydantic-docs.helpmanual.io/usage/exporting_models/#json_encoders" class="external-link" target="_blank">більше інформації дивись у документації</a>.
|
||||
* `frozenset`:
|
||||
* У запитах і відповідях це буде оброблено так само, як і `set`:
|
||||
* У запитах список буде зчитано, дублікати будуть видалені та він буде перетворений на `set`.
|
||||
* У відповідях, `set` буде перетворений на `list`.
|
||||
* Згенерована схема буде вказувати, що значення `set` є унікальними (з використанням JSON Schema's `uniqueItems`).
|
||||
* `bytes`:
|
||||
* Стандартний Пайтонівський `bytes`.
|
||||
* У запитах і відповідях це буде оброблено як `str`.
|
||||
* Згенерована схема буде вказувати, що це `str` з "форматом" `binary`.
|
||||
* `Decimal`:
|
||||
* Стандартний Пайтонівський `Decimal`.
|
||||
* У запитах і відповідях це буде оброблено так само, як і `float`.
|
||||
* Ви можете перевірити всі дійсні типи даних Pydantic тут: <a href="https://pydantic-docs.helpmanual.io/usage/types" class="external-link" target="_blank">типи даних Pydantic</a>.
|
||||
|
||||
## Приклад
|
||||
|
||||
Ось приклад *path operation* з параметрами, використовуючи деякі з вищезазначених типів.
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="1 3 12-16"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="1 3 12-16"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="1 3 13-17"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ non-Annotated"
|
||||
|
||||
!!! tip
|
||||
Бажано використовувати `Annotated` версію, якщо це можливо.
|
||||
|
||||
```Python hl_lines="1 2 11-15"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+ non-Annotated"
|
||||
|
||||
!!! tip
|
||||
Бажано використовувати `Annotated` версію, якщо це можливо.
|
||||
|
||||
```Python hl_lines="1 2 12-16"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001.py!}
|
||||
```
|
||||
|
||||
Зверніть увагу, що параметри всередині функції мають свій звичайний тип даних, і ви можете, наприклад, виконувати звичайні маніпуляції з датами, такі як:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="18-19"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="18-19"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="19-20"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ non-Annotated"
|
||||
|
||||
!!! tip
|
||||
Бажано використовувати `Annotated` версію, якщо це можливо.
|
||||
|
||||
```Python hl_lines="17-18"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+ non-Annotated"
|
||||
|
||||
!!! tip
|
||||
Бажано використовувати `Annotated` версію, якщо це можливо.
|
||||
|
||||
```Python hl_lines="18-19"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001.py!}
|
||||
```
|
||||
80
docs/uk/docs/tutorial/index.md
Normal file
80
docs/uk/docs/tutorial/index.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Туторіал - Посібник користувача
|
||||
|
||||
У цьому посібнику показано, як користуватися **FastAPI** з більшістю його функцій, крок за кроком.
|
||||
|
||||
Кожен розділ поступово надбудовується на попередні, але він структурований на окремі теми, щоб ви могли перейти безпосередньо до будь-якої конкретної, щоб вирішити ваші конкретні потреби API.
|
||||
|
||||
Він також створений як довідник для роботи у майбутньому.
|
||||
|
||||
Тож ви можете повернутися і побачити саме те, що вам потрібно.
|
||||
|
||||
## Запустіть код
|
||||
|
||||
Усі блоки коду можна скопіювати та використовувати безпосередньо (це фактично перевірені файли Python).
|
||||
|
||||
Щоб запустити будь-який із прикладів, скопіюйте код у файл `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[standard]"
|
||||
```
|
||||
|
||||
І те саме для кожної з опціональних залежностей, які ви хочете використовувати.
|
||||
|
||||
## Розширений посібник користувача
|
||||
|
||||
Існує також **Розширений посібник користувача**, який ви зможете прочитати пізніше після цього **Туторіал - Посібник користувача**.
|
||||
|
||||
**Розширений посібник користувача** засновано на цьому, використовує ті самі концепції та навчає вас деяким додатковим функціям.
|
||||
|
||||
Але вам слід спочатку прочитати **Туторіал - Посібник користувача** (те, що ви зараз читаєте).
|
||||
|
||||
Він розроблений таким чином, що ви можете створити повну програму лише за допомогою **Туторіал - Посібник користувача**, а потім розширити її різними способами, залежно від ваших потреб, використовуючи деякі з додаткових ідей з **Розширеного посібника користувача** .
|
||||
333
docs/vi/docs/tutorial/first-steps.md
Normal file
333
docs/vi/docs/tutorial/first-steps.md
Normal file
@@ -0,0 +1,333 @@
|
||||
# Những bước đầu tiên
|
||||
|
||||
Tệp tin FastAPI đơn giản nhất có thể trông như này:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Sao chép sang một tệp tin `main.py`.
|
||||
|
||||
Chạy live server:
|
||||
|
||||
<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
|
||||
Câu lệnh `uvicorn main:app` được giải thích như sau:
|
||||
|
||||
* `main`: tệp tin `main.py` (một Python "mô đun").
|
||||
* `app`: một object được tạo ra bên trong `main.py` với dòng `app = FastAPI()`.
|
||||
* `--reload`: làm server khởi động lại sau mỗi lần thay đổi. Chỉ sử dụng trong môi trường phát triển.
|
||||
|
||||
Trong output, có một dòng giống như:
|
||||
|
||||
```hl_lines="4"
|
||||
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
Dòng đó cho thấy URL, nơi mà app của bạn đang được chạy, trong máy local của bạn.
|
||||
|
||||
### Kiểm tra
|
||||
|
||||
Mở trình duyệt của bạn tại <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>.
|
||||
|
||||
Bạn sẽ thấy một JSON response như:
|
||||
|
||||
```JSON
|
||||
{"message": "Hello World"}
|
||||
```
|
||||
|
||||
### Tài liệu tương tác API
|
||||
|
||||
Bây giờ tới <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
Bạn sẽ thấy một tài liệu tương tác API (cung cấp bởi <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
|
||||
|
||||

|
||||
|
||||
### Phiên bản thay thế của tài liệu API
|
||||
|
||||
Và bây giờ tới <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
Bạn sẽ thấy một bản thay thế của tài liệu (cung cấp bởi <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
|
||||

|
||||
|
||||
### OpenAPI
|
||||
|
||||
**FastAPI** sinh một "schema" với tất cả API của bạn sử dụng tiêu chuẩn **OpenAPI** cho định nghĩa các API.
|
||||
|
||||
#### "Schema"
|
||||
|
||||
Một "schema" là một định nghĩa hoặc mô tả thứ gì đó. Không phải code triển khai của nó, nhưng chỉ là một bản mô tả trừu tượng.
|
||||
|
||||
#### API "schema"
|
||||
|
||||
Trong trường hợp này, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> là một bản mô tả bắt buộc cơ chế định nghĩa API của bạn.
|
||||
|
||||
Định nghĩa cấu trúc này bao gồm những đường dẫn API của bạn, các tham số có thể có,...
|
||||
|
||||
#### "Cấu trúc" dữ liệu
|
||||
|
||||
Thuật ngữ "cấu trúc" (schema) cũng có thể được coi như là hình dạng của dữ liệu, tương tự như một JSON content.
|
||||
|
||||
Trong trường hợp đó, nó có nghĩa là các thuộc tính JSON và các kiểu dữ liệu họ có,...
|
||||
|
||||
#### OpenAPI và JSON Schema
|
||||
|
||||
OpenAPI định nghĩa một cấu trúc API cho API của bạn. Và cấu trúc đó bao gồm các dịnh nghĩa (or "schema") về dữ liệu được gửi đi và nhận về bởi API của bạn, sử dụng **JSON Schema**, một tiêu chuẩn cho cấu trúc dữ liệu JSON.
|
||||
|
||||
#### Kiểm tra `openapi.json`
|
||||
|
||||
Nếu bạn tò mò về việc cấu trúc OpenAPI nhìn như thế nào thì FastAPI tự động sinh một JSON (schema) với các mô tả cho tất cả API của bạn.
|
||||
|
||||
Bạn có thể thấy nó trực tiếp tại: <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
|
||||
|
||||
Nó sẽ cho thấy một JSON bắt đầu giống như:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"info": {
|
||||
"title": "FastAPI",
|
||||
"version": "0.1.0"
|
||||
},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
|
||||
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
#### OpenAPI dùng để làm gì?
|
||||
|
||||
Cấu trúc OpenAPI là sức mạnh của tài liệu tương tác.
|
||||
|
||||
Và có hàng tá các bản thay thế, tất cả đều dựa trên OpenAPI. Bạn có thể dễ dàng thêm bất kì bản thay thế bào cho ứng dụng của bạn được xây dựng với **FastAPI**.
|
||||
|
||||
Bạn cũng có thể sử dụng nó để sinh code tự động, với các client giao viết qua API của bạn. Ví dụ, frontend, mobile hoặc các ứng dụng IoT.
|
||||
|
||||
## Tóm lại, từng bước một
|
||||
|
||||
### Bước 1: import `FastAPI`
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
`FastAPI` là một Python class cung cấp tất cả chức năng cho API của bạn.
|
||||
|
||||
!!! note "Chi tiết kĩ thuật"
|
||||
`FastAPI` là một class kế thừa trực tiếp `Starlette`.
|
||||
|
||||
Bạn cũng có thể sử dụng tất cả <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> chức năng với `FastAPI`.
|
||||
|
||||
### Bước 2: Tạo một `FastAPI` "instance"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Biến `app` này là một "instance" của class `FastAPI`.
|
||||
|
||||
Đây sẽ là điểm cốt lõi để tạo ra tất cả API của bạn.
|
||||
|
||||
`app` này chính là điều được nhắc tới bởi `uvicorn` trong câu lệnh:
|
||||
|
||||
<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>
|
||||
|
||||
Nếu bạn tạo ứng dụng của bạn giống như:
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/first_steps/tutorial002.py!}
|
||||
```
|
||||
|
||||
Và đặt nó trong một tệp tin `main.py`, sau đó bạn sẽ gọi `uvicorn` giống như:
|
||||
|
||||
<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>
|
||||
|
||||
### Bước 3: tạo một *đường dẫn toán tử*
|
||||
|
||||
#### Đường dẫn
|
||||
|
||||
"Đường dẫn" ở đây được nhắc tới là phần cuối cùng của URL bắt đầu từ `/`.
|
||||
|
||||
Do đó, trong một URL nhìn giống như:
|
||||
|
||||
```
|
||||
https://example.com/items/foo
|
||||
```
|
||||
|
||||
...đường dẫn sẽ là:
|
||||
|
||||
```
|
||||
/items/foo
|
||||
```
|
||||
|
||||
!!! info
|
||||
Một đường dẫn cũng là một cách gọi chung cho một "endpoint" hoặc một "route".
|
||||
|
||||
Trong khi xây dựng một API, "đường dẫn" là các chính để phân tách "mối quan hệ" và "tài nguyên".
|
||||
|
||||
#### Toán tử (Operation)
|
||||
|
||||
"Toán tử" ở đây được nhắc tới là một trong các "phương thức" HTTP.
|
||||
|
||||
Một trong những:
|
||||
|
||||
* `POST`
|
||||
* `GET`
|
||||
* `PUT`
|
||||
* `DELETE`
|
||||
|
||||
...và một trong những cái còn lại:
|
||||
|
||||
* `OPTIONS`
|
||||
* `HEAD`
|
||||
* `PATCH`
|
||||
* `TRACE`
|
||||
|
||||
Trong giao thức HTTP, bạn có thể giao tiếp trong mỗi đường dẫn sử dụng một (hoặc nhiều) trong các "phương thức này".
|
||||
|
||||
---
|
||||
|
||||
Khi xây dựng các API, bạn thường sử dụng cụ thể các phương thức HTTP này để thực hiện một hành động cụ thể.
|
||||
|
||||
Thông thường, bạn sử dụng
|
||||
|
||||
* `POST`: để tạo dữ liệu.
|
||||
* `GET`: để đọc dữ liệu.
|
||||
* `PUT`: để cập nhật dữ liệu.
|
||||
* `DELETE`: để xóa dữ liệu.
|
||||
|
||||
Do đó, trong OpenAPI, mỗi phương thức HTTP được gọi là một "toán tử (operation)".
|
||||
|
||||
Chúng ta cũng sẽ gọi chúng là "**các toán tử**".
|
||||
|
||||
#### Định nghĩa moojt *decorator cho đường dẫn toán tử*
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
`@app.get("/")` nói **FastAPI** rằng hàm bên dưới có trách nhiệm xử lí request tới:
|
||||
|
||||
* đường dẫn `/`
|
||||
* sử dụng một <abbr title="an HTTP GET method">toán tử<code>get</code></abbr>
|
||||
|
||||
!!! info Thông tin về "`@decorator`"
|
||||
Cú pháp `@something` trong Python được gọi là một "decorator".
|
||||
|
||||
Bạn đặt nó trên một hàm. Giống như một chiếc mũ xinh xắn (Tôi ddonas đó là lí do mà thuật ngữ này ra đời).
|
||||
|
||||
Một "decorator" lấy một hàm bên dưới và thực hiện một vài thứ với nó.
|
||||
|
||||
Trong trường hợp của chúng ta, decorator này nói **FastAPI** rằng hàm bên dưới ứng với **đường dẫn** `/` và một **toán tử** `get`.
|
||||
|
||||
Nó là một "**decorator đường dẫn toán tử**".
|
||||
|
||||
Bạn cũng có thể sử dụng với các toán tử khác:
|
||||
|
||||
* `@app.post()`
|
||||
* `@app.put()`
|
||||
* `@app.delete()`
|
||||
|
||||
Và nhiều hơn với các toán tử còn lại:
|
||||
|
||||
* `@app.options()`
|
||||
* `@app.head()`
|
||||
* `@app.patch()`
|
||||
* `@app.trace()`
|
||||
|
||||
!!! tip
|
||||
Bạn thoải mái sử dụng mỗi toán tử (phương thức HTTP) như bạn mơ ước.
|
||||
|
||||
**FastAPI** không bắt buộc bất kì ý nghĩa cụ thể nào.
|
||||
|
||||
Thông tin ở đây được biểu thị như là một chỉ dẫn, không phải là một yêu cầu bắt buộc.
|
||||
|
||||
Ví dụ, khi sử dụng GraphQL bạn thông thường thực hiện tất cả các hành động chỉ bằng việc sử dụng các toán tử `POST`.
|
||||
|
||||
### Step 4: Định nghĩa **hàm cho đường dẫn toán tử**
|
||||
|
||||
Đây là "**hàm cho đường dẫn toán tử**":
|
||||
|
||||
* **đường dẫn**: là `/`.
|
||||
* **toán tử**: là `get`.
|
||||
* **hàm**: là hàm bên dưới "decorator" (bên dưới `@app.get("/")`).
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Đây là một hàm Python.
|
||||
|
||||
Nó sẽ được gọi bởi **FastAPI** bất cứ khi nào nó nhận một request tới URL "`/`" sử dụng một toán tử `GET`.
|
||||
|
||||
Trong trường hợp này, nó là một hàm `async`.
|
||||
|
||||
---
|
||||
|
||||
Bạn cũng có thể định nghĩa nó như là một hàm thông thường thay cho `async def`:
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/first_steps/tutorial003.py!}
|
||||
```
|
||||
|
||||
!!! note
|
||||
Nếu bạn không biết sự khác nhau, kiểm tra [Async: *"Trong khi vội vàng?"*](../async.md#in-a-hurry){.internal-link target=_blank}.
|
||||
|
||||
### Bước 5: Nội dung trả về
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Bạn có thể trả về một `dict`, `list`, một trong những giá trị đơn như `str`, `int`,...
|
||||
|
||||
Bạn cũng có thể trả về Pydantic model (bạn sẽ thấy nhiều hơn về nó sau).
|
||||
|
||||
Có nhiều object và model khác nhau sẽ được tự động chuyển đổi sang JSON (bao gồm cả ORM,...). Thử sử dụng loại ưa thích của bạn, nó có khả năng cao đã được hỗ trợ.
|
||||
|
||||
## Tóm lại
|
||||
|
||||
* Import `FastAPI`.
|
||||
* Tạo một `app` instance.
|
||||
* Viết một **decorator cho đường dẫn toán tử** (giống như `@app.get("/")`).
|
||||
* Viết một **hàm cho đường dẫn toán tử** (giống như `def root(): ...` ở trên).
|
||||
* Chạy server trong môi trường phát triển (giống như `uvicorn main:app --reload`).
|
||||
80
docs/vi/docs/tutorial/index.md
Normal file
80
docs/vi/docs/tutorial/index.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Hướng dẫn sử dụng
|
||||
|
||||
Hướng dẫn này cho bạn thấy từng bước cách sử dụng **FastAPI** đa số các tính năng của nó.
|
||||
|
||||
Mỗi phần được xây dựng từ những phần trước đó, nhưng nó được cấu trúc thành các chủ đề riêng biệt, do đó bạn có thể xem trực tiếp từng phần cụ thể bất kì để giải quyết những API cụ thể mà bạn cần.
|
||||
|
||||
Nó cũng được xây dựng để làm việc như một tham chiếu trong tương lai.
|
||||
|
||||
Do đó bạn có thể quay lại và tìm chính xác những gì bạn cần.
|
||||
|
||||
## Chạy mã
|
||||
|
||||
Tất cả các code block có thể được sao chép và sử dụng trực tiếp (chúng thực chất là các tệp tin Python đã được kiểm thử).
|
||||
|
||||
Để chạy bất kì ví dụ nào, sao chép code tới tệp tin `main.py`, và bắt đầu `uvicorn` với:
|
||||
|
||||
<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>
|
||||
|
||||
**Khuyến khích** bạn viết hoặc sao chép code, sửa và chạy nó ở local.
|
||||
|
||||
Sử dụng nó trong trình soạn thảo của bạn thực sự cho bạn thấy những lợi ích của FastAPI, thấy được cách bạn viết code ít hơn, tất cả đều được type check, autocompletion,...
|
||||
|
||||
---
|
||||
|
||||
## Cài đặt FastAPI
|
||||
|
||||
Bước đầu tiên là cài đặt FastAPI.
|
||||
|
||||
Với hướng dẫn này, bạn có thể muốn cài đặt nó với tất cả các phụ thuộc và tính năng tùy chọn:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install "fastapi[all]"
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
...dó cũng bao gồm `uvicorn`, bạn có thể sử dụng như một server để chạy code của bạn.
|
||||
|
||||
!!! note
|
||||
Bạn cũng có thể cài đặt nó từng phần.
|
||||
|
||||
Đây là những gì bạn có thể sẽ làm một lần duy nhất bạn muốn triển khai ứng dụng của bạn lên production:
|
||||
|
||||
```
|
||||
pip install fastapi
|
||||
```
|
||||
|
||||
Cũng cài đặt `uvicorn` để làm việc như một server:
|
||||
|
||||
```
|
||||
pip install "uvicorn[standard]"
|
||||
```
|
||||
|
||||
Và tương tự với từng phụ thuộc tùy chọn mà bạn muốn sử dụng.
|
||||
|
||||
## Hướng dẫn nâng cao
|
||||
|
||||
Cũng có một **Hướng dẫn nâng cao** mà bạn có thể đọc nó sau **Hướng dẫn sử dụng**.
|
||||
|
||||
**Hướng dẫn sử dụng nâng cao**, xây dựng dựa trên cái này, sử dụng các khái niệm tương tự, và dạy bạn những tính năng mở rộng.
|
||||
|
||||
Nhưng bạn nên đọc **Hướng dẫn sử dụng** đầu tiên (những gì bạn đang đọc).
|
||||
|
||||
Nó được thiết kế do đó bạn có thể xây dựng một ứng dụng hoàn chỉnh chỉ với **Hướng dẫn sử dụng**, và sau đó mở rộng nó theo các cách khác nhau, phụ thuộc vào những gì bạn cần, sử dụng một vài ý tưởng bổ sung từ **Hướng dẫn sử dụng nâng cao**.
|
||||
470
docs/yo/docs/index.md
Normal file
470
docs/yo/docs/index.md
Normal file
@@ -0,0 +1,470 @@
|
||||
<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>Ìlànà wẹ́ẹ́bù FastAPI, iṣẹ́ gíga, ó rọrùn láti kọ̀, o yára láti kóòdù, ó sì ṣetán fún iṣelọpọ ní lílo</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg?event=push&branch=master" alt="Test">
|
||||
</a>
|
||||
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://coverage-badge.samuelcolvin.workers.dev/tiangolo/fastapi.svg" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
**Àkọsílẹ̀**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
|
||||
|
||||
**Orisun Kóòdù**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
|
||||
|
||||
---
|
||||
|
||||
FastAPI jẹ́ ìgbàlódé, tí ó yára (iṣẹ-giga), ìlànà wẹ́ẹ́bù fún kikọ àwọn API pẹ̀lú Python 3.7+ èyí tí ó da lori àwọn ìtọ́kasí àmì irúfẹ́ Python.
|
||||
|
||||
Àwọn ẹya pàtàkì ni:
|
||||
|
||||
* **Ó yára**: Iṣẹ tí ó ga púpọ̀, tí ó wa ni ibamu pẹ̀lú **NodeJS** àti **Go** (ọpẹ si Starlette àti Pydantic). [Ọkan nínú àwọn ìlànà Python ti o yára jùlọ ti o wa](#performance).
|
||||
* **Ó yára láti kóòdù**: O mu iyara pọ si láti kọ àwọn ẹya tuntun kóòdù nipasẹ "Igba ìdá ọgọ́rùn-ún" (i.e. 200%) si "ọ̀ọ́dúrún ìdá ọgọ́rùn-ún" (i.e. 300%).
|
||||
* **Àìtọ́ kékeré**: O n din aṣiṣe ku bi ọgbon ìdá ọgọ́rùn-ún (i.e. 40%) ti eda eniyan (oṣiṣẹ kóòdù) fa. *
|
||||
* **Ọgbọ́n àti ìmọ̀**: Atilẹyin olootu nla. <abbr title="a tun le pe ni olùrànlọ́wọ́ alaifiọwọkan alaifọwọyi, olùpari iṣẹ-ṣiṣe, Oloye">Ìparí</abbr> nibi gbogbo. Àkókò díẹ̀ nipa wíwá ibi tí ìṣòro kóòdù wà.
|
||||
* **Irọrun**: A kọ kí ó le rọrun láti lo àti láti kọ ẹkọ nínú rè. Ó máa fún ọ ní àkókò díẹ̀ látı ka àkọsílẹ.
|
||||
* **Ó kúkurú ní kikọ**: Ó dín àtúnkọ àti àtúntò kóòdù kù. Ìkéde àṣàyàn kọ̀ọ̀kan nínú rẹ̀ ní ọ̀pọ̀lọpọ̀ àwọn ìlò. O ṣe iranlọwọ láti má ṣe ní ọ̀pọ̀lọpọ̀ àṣìṣe.
|
||||
* **Ó lágbára**: Ó ń ṣe àgbéjáde kóòdù tí ó ṣetán fún ìṣelọ́pọ̀. Pẹ̀lú àkọsílẹ̀ tí ó máa ṣàlàyé ara rẹ̀ fún ẹ ní ìbáṣepọ̀ aládàáṣiṣẹ́ pẹ̀lú rè.
|
||||
* **Ajohunše/Ìtọ́kasí**: Ó da lori (àti ibamu ni kikun pẹ̀lú) àwọn ìmọ ajohunše/ìtọ́kasí fún àwọn API: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (èyí tí a mọ tẹlẹ si Swagger) àti <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
|
||||
<small>* iṣiro yi da lori àwọn idanwo tí ẹgbẹ ìdàgbàsókè FastAPI ṣe, nígbàtí wọn kọ àwọn ohun elo iṣelọpọ kóòdù pẹ̀lú rẹ.</small>
|
||||
|
||||
## Àwọn onígbọ̀wọ́
|
||||
|
||||
<!-- sponsors -->
|
||||
|
||||
{% if sponsors %}
|
||||
{% for sponsor in sponsors.gold -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor -%}
|
||||
{%- for sponsor in sponsors.silver -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<!-- /sponsors -->
|
||||
|
||||
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Àwọn onígbọ̀wọ́ míràn</a>
|
||||
|
||||
## Àwọn ero àti èsì
|
||||
|
||||
"_[...] Mò ń lo **FastAPI** púpọ̀ ní lẹ́nu àìpẹ́ yìí. [...] Mo n gbero láti lo o pẹ̀lú àwọn ẹgbẹ mi fún gbogbo iṣẹ **ML wa ni Microsoft**. Diẹ nínú wọn ni afikun ti ifilelẹ àwọn ẹya ara ti ọja **Windows** wa pẹ̀lú àwọn ti **Office**._"
|
||||
|
||||
<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>
|
||||
|
||||
---
|
||||
|
||||
"_A gba àwọn ohun èlò ìwé afọwọkọ **FastAPI** tí kò yí padà láti ṣẹ̀dá olùpín **REST** tí a lè béèrè lọ́wọ́ rẹ̀ láti gba **àsọtẹ́lẹ̀**. [fún 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** ni inudidun láti kede itusilẹ orisun kóòdù ti ìlànà iṣọkan **iṣakoso Ìṣòro** wa: **Ìfiránṣẹ́**! [a kọ pẹ̀lú **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>
|
||||
|
||||
---
|
||||
|
||||
"_Inú mi dùn púpọ̀ nípa **FastAPI**. Ó mú inú ẹnì dùn púpọ̀!_"
|
||||
|
||||
<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>
|
||||
|
||||
---
|
||||
|
||||
"_Ní tòótọ́, ohun tí o kọ dára ó sì tún dán. Ní ọ̀pọ̀lọpọ̀ ọ̀nà, ohun tí mo fẹ́ kí **Hug** jẹ́ nìyẹn - ó wúni lórí gan-an láti rí ẹnìkan tí ó kọ́ nǹkan bí èyí._"
|
||||
|
||||
<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>
|
||||
|
||||
---
|
||||
|
||||
"_Ti o ba n wa láti kọ ọkan **ìlànà igbalode** fún kikọ àwọn REST API, ṣayẹwo **FastAPI** [...] Ó yára, ó rọrùn láti lò, ó sì rọrùn láti kọ́[...]_"
|
||||
|
||||
"_A ti yipada si **FastAPI** fún **APIs** wa [...] Mo lérò pé wà á fẹ́ràn rẹ̀ [...]_"
|
||||
|
||||
<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>
|
||||
|
||||
---
|
||||
|
||||
"_Ti ẹnikẹni ba n wa láti kọ iṣelọpọ API pẹ̀lú Python, èmi yóò ṣe'dúró fún **FastAPI**. Ó jẹ́ ohun tí **àgbékalẹ̀ rẹ̀ lẹ́wà**, **ó rọrùn láti lò** àti wipe ó ni **ìwọ̀n gíga**, o tí dí **bọtini paati** nínú alakọkọ API ìdàgbàsókè kikọ fún wa, àti pe o ni ipa lori adaṣiṣẹ àti àwọn iṣẹ gẹ́gẹ́ bíi Onímọ̀-ẹ̀rọ TAC tí órí Íńtánẹ́ẹ̀tì_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**, FastAPI ti 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>
|
||||
|
||||
Ti o ba n kọ ohun èlò <abbr title="Command Line Interface">CLI</abbr> láti ṣeé lọ nínú ohun èlò lori ebute kọmputa dipo API, ṣayẹwo <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
|
||||
|
||||
**Typer** jẹ́ àbúrò ìyá FastAPI kékeré. Àti pé wọ́n kọ́ láti jẹ́ **FastAPI ti CLIs**. ⌨️ 🚀
|
||||
|
||||
## Èròjà
|
||||
|
||||
Python 3.7+
|
||||
|
||||
FastAPI dúró lórí àwọn èjìká tí àwọn òmíràn:
|
||||
|
||||
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> fún àwọn ẹ̀yà ayélujára.
|
||||
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> fún àwọn ẹ̀yà àkójọf'áyẹ̀wò.
|
||||
|
||||
## Fifi sórí ẹrọ
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install fastapi
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
Iwọ yóò tún nílò olupin ASGI, fún iṣelọpọ bii <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> tabi <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install "uvicorn[standard]"
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## Àpẹẹrẹ
|
||||
|
||||
### Ṣẹ̀dá rẹ̀
|
||||
|
||||
* Ṣẹ̀dá fáìlì `main.py (èyí tíí ṣe, akọkọ.py)` pẹ̀lú:
|
||||
|
||||
```Python
|
||||
from typing import Union
|
||||
|
||||
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: Union[str, None] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
<details markdown="1">
|
||||
<summary>Tàbí lò <code>async def</code>...</summary>
|
||||
|
||||
Tí kóòdù rẹ̀ bá ń lò `async` / `await`, lò `async def`:
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
from typing import Union
|
||||
|
||||
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: Union[str, None] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
**Akiyesi**:
|
||||
|
||||
Tí o kò bá mọ̀, ṣàyẹ̀wò ibi tí a ti ní _"In a hurry?"_ (i.e. _"Ní kíákíá?"_) nípa <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` nínú àkọsílẹ̀</a>.
|
||||
|
||||
</details>
|
||||
|
||||
### Mu ṣiṣẹ
|
||||
|
||||
Mú olupin ṣiṣẹ pẹ̀lú:
|
||||
|
||||
<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>Nipa aṣẹ kóòdù náà <code>uvicorn main:app --reload</code>...</summary>
|
||||
|
||||
Àṣẹ `uvicorn main:app` ń tọ́ka sí:
|
||||
|
||||
* `main`: fáìlì náà 'main.py' (Python "module").
|
||||
* `app` jẹ object( i.e. nǹkan) tí a ṣẹ̀dá nínú `main.py` pẹ̀lú ilà `app = FastAPI()`.
|
||||
* `--reload`: èyí yóò jẹ́ ki olupin tún bẹ̀rẹ̀ lẹ́hìn àwọn àyípadà kóòdù. Jọ̀wọ́, ṣe èyí fún ìdàgbàsókè kóòdù nìkan, má ṣe é ṣe lori àgbéjáde kóòdù tabi fún iṣelọpọ kóòdù.
|
||||
|
||||
|
||||
</details>
|
||||
|
||||
### Ṣayẹwo rẹ
|
||||
|
||||
Ṣii aṣàwákiri kọ̀ǹpútà rẹ ni <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>.
|
||||
|
||||
Ìwọ yóò sì rí ìdáhùn JSON bíi:
|
||||
|
||||
```JSON
|
||||
{"item_id": 5, "q": "somequery"}
|
||||
```
|
||||
|
||||
O tí ṣẹ̀dá API èyí tí yóò:
|
||||
|
||||
* Gbà àwọn ìbéèrè HTTP ni àwọn _ipa ọ̀nà_ `/` àti `/items/{item_id}`.
|
||||
* Èyí tí àwọn _ipa ọ̀nà_ (i.e. _paths_) méjèèjì gbà àwọn <em>iṣẹ</em> `GET` (a tun mọ si _àwọn ọna_ HTTP).
|
||||
* Èyí tí _ipa ọ̀nà_ (i.e. _paths_) `/items/{item_id}` ní _àwọn ohun-ini ipa ọ̀nà_ tí ó yẹ kí ó jẹ́ `int` i.e. `ÒǸKÀ`.
|
||||
* Èyí tí _ipa ọ̀nà_ (i.e. _paths_) `/items/{item_id}` ní àṣàyàn `str` _àwọn ohun-ini_ (i.e. _query parameter_) `q`.
|
||||
|
||||
### Ìbáṣepọ̀ àkọsílẹ̀ API
|
||||
|
||||
Ní báyìí, lọ sí <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
Lẹ́yìn náà, iwọ yóò rí ìdáhùn àkọsílẹ̀ API tí ó jẹ́ ìbáṣepọ̀ alaifọwọyi/aládàáṣiṣẹ́ (tí a pèṣè nípaṣẹ̀ <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
|
||||
|
||||

|
||||
|
||||
### Ìdàkejì àkọsílẹ̀ API
|
||||
|
||||
Ní báyìí, lọ sí <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
Wà á rí àwọn àkọsílẹ̀ aládàáṣiṣẹ́ mìíràn (tí a pese nipasẹ <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
|
||||

|
||||
|
||||
## Àpẹẹrẹ ìgbésókè mìíràn
|
||||
|
||||
Ní báyìí ṣe àtúnṣe fáìlì `main.py` láti gba kókó èsì láti inú ìbéèrè `PUT`.
|
||||
|
||||
Ní báyìí, ṣe ìkéde kókó èsì API nínú kóòdù rẹ nipa lílo àwọn ìtọ́kasí àmì irúfẹ́ Python, ọpẹ́ pàtàkìsi sí Pydantic.
|
||||
|
||||
```Python hl_lines="4 9-12 25-27"
|
||||
from typing import Union
|
||||
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
is_offer: Union[bool, None] = None
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: Union[str, None] = 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}
|
||||
```
|
||||
|
||||
Olupin yóò tún ṣe àtúnṣe laifọwọyi/aládàáṣiṣẹ́ (nítorí wípé ó se àfikún `-reload` si àṣẹ kóòdù `uvicorn` lókè).
|
||||
|
||||
### Ìbáṣepọ̀ ìgbésókè àkọsílẹ̀ API
|
||||
|
||||
Ní báyìí, lọ sí <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
* Ìbáṣepọ̀ àkọsílẹ̀ API yóò ṣe imudojuiwọn àkọsílẹ̀ API laifọwọyi, pẹ̀lú kókó èsì ìdáhùn API tuntun:
|
||||
|
||||

|
||||
|
||||
* Tẹ bọtini "Gbiyanju rẹ" i.e. "Try it out", yóò gbà ọ́ láàyè láti jẹ́ kí ó tẹ́ àlàyé tí ó nílò kí ó le sọ̀rọ̀ tààrà pẹ̀lú API:
|
||||
|
||||

|
||||
|
||||
* Lẹhinna tẹ bọtini "Ṣiṣe" i.e. "Execute", olùmúlò (i.e. user interface) yóò sọrọ pẹ̀lú API rẹ, yóò ṣe afiranṣẹ àwọn èròjà, pàápàá jùlọ yóò gba àwọn àbájáde yóò si ṣafihan wọn loju ìbòjú:
|
||||
|
||||

|
||||
|
||||
### Ìdàkejì ìgbésókè àkọsílẹ̀ API
|
||||
|
||||
Ní báyìí, lọ sí <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
* Ìdàkejì àkọsílẹ̀ API yóò ṣ'afihan ìbéèrè èròjà/pàrámítà tuntun àti kókó èsì ti API:
|
||||
|
||||

|
||||
|
||||
### Àtúnyẹ̀wò
|
||||
|
||||
Ni akopọ, ìwọ yóò kéde ni **kete** àwọn iru èròjà/pàrámítà, kókó èsì API, abbl (i.e. àti bẹbẹ lọ), bi àwọn èròjà iṣẹ.
|
||||
|
||||
O ṣe ìyẹn pẹ̀lú irúfẹ́ àmì ìtọ́kasí ìgbàlódé Python.
|
||||
|
||||
O ò nílò láti kọ́ síńtáàsì tuntun, ìlànà tàbí ọ̀wọ́ kíláàsì kan pàtó, abbl (i.e. àti bẹbẹ lọ).
|
||||
|
||||
Ìtọ́kasí **Python 3.7+**
|
||||
|
||||
Fún àpẹẹrẹ, fún `int`:
|
||||
|
||||
```Python
|
||||
item_id: int
|
||||
```
|
||||
|
||||
tàbí fún àwòṣe `Item` tí ó nira díẹ̀ síi:
|
||||
|
||||
```Python
|
||||
item: Item
|
||||
```
|
||||
|
||||
... àti pẹ̀lú ìkéde kan ṣoṣo yẹn ìwọ yóò gbà:
|
||||
|
||||
* Atilẹyin olootu, pẹ̀lú:
|
||||
* Pipari.
|
||||
* Àyẹ̀wò irúfẹ́ àmì ìtọ́kasí.
|
||||
* Ìfọwọ́sí àkójọf'áyẹ̀wò (i.e. data):
|
||||
* Aṣiṣe alaifọwọyi/aládàáṣiṣẹ́ àti aṣiṣe ti ó hàn kedere nígbàtí àwọn àkójọf'áyẹ̀wò (i.e. data) kò wulo tabi tí kò fẹsẹ̀ múlẹ̀.
|
||||
* Ìfọwọ́sí fún ohun elo JSON tí ó jìn gan-an.
|
||||
* <abbr title="also known as: serialization, parsing, marshalling">Ìyípadà</abbr> tí input àkójọf'áyẹ̀wò: tí ó wà láti nẹtiwọọki si àkójọf'áyẹ̀wò àti irúfẹ́ àmì ìtọ́kasí Python. Ó ń ka láti:
|
||||
* JSON.
|
||||
* èròjà ọ̀nà tí ò gbé gbà.
|
||||
* èròjà ìbéèrè.
|
||||
* Àwọn Kúkì
|
||||
* Àwọn Àkọlé
|
||||
* Àwọn Fọọmu
|
||||
* Àwọn Fáìlì
|
||||
* <abbr title="a tún má ń pè ni: serialization, parsing, marshalling">Ìyípadà</abbr> èsì àkójọf'áyẹ̀wò: yíyípadà láti àkójọf'áyẹ̀wò àti irúfẹ́ àmì ìtọ́kasí Python si nẹtiwọọki (gẹ́gẹ́ bí JSON):
|
||||
* Yí irúfẹ́ àmì ìtọ́kasí padà (`str`, `int`, `float`, `bool`, `list`, abbl i.e. àti bèbè ló).
|
||||
* Àwọn ohun èlò `datetime`.
|
||||
* Àwọn ohun èlò `UUID`.
|
||||
* Àwọn awoṣẹ́ ibi ìpamọ́ àkójọf'áyẹ̀wò.
|
||||
* ...àti ọ̀pọ̀lọpọ̀ díẹ̀ síi.
|
||||
* Ìbáṣepọ̀ àkọsílẹ̀ API aládàáṣiṣẹ́, pẹ̀lú ìdàkejì àgbékalẹ̀-àwọn-olùmúlò (i.e user interfaces) méjì:
|
||||
* Àgbékalẹ̀-olùmúlò Swagger.
|
||||
* ReDoc.
|
||||
|
||||
---
|
||||
|
||||
Nisinsin yi, tí ó padà sí àpẹẹrẹ ti tẹ́lẹ̀, **FastAPI** yóò:
|
||||
|
||||
* Fọwọ́ sí i pé `item_id` wà nínú ọ̀nà ìbéèrè HTTP fún `GET` àti `PUT`.
|
||||
* Fọwọ́ sí i pé `item_id` jẹ́ irúfẹ́ àmì ìtọ́kasí `int` fún ìbéèrè HTTP `GET` àti `PUT`.
|
||||
* Tí kìí bá ṣe bẹ, oníbàárà yóò ríi àṣìṣe tí ó wúlò, kedere.
|
||||
* Ṣàyẹ̀wò bóyá ìbéèrè àṣàyàn pàrámítà kan wà tí orúkọ rẹ̀ ń jẹ́ `q` (gẹ́gẹ́ bíi `http://127.0.0.1:8000/items/foo?q=somequery`) fún ìbéèrè HTTP `GET`.
|
||||
* Bí wọ́n ṣe kéde pàrámítà `q` pẹ̀lú `= None`, ó jẹ́ àṣàyàn (i.e optional).
|
||||
* Láìsí `None` yóò nílò (gẹ́gẹ́ bí kókó èsì ìbéèrè HTTP ṣe wà pẹ̀lú `PUT`).
|
||||
* Fún àwọn ìbéèrè HTTP `PUT` sí `/items/{item_id}`, kà kókó èsì ìbéèrè HTTP gẹ́gẹ́ bí JSON:
|
||||
* Ṣàyẹ̀wò pé ó ní àbùdá tí ó nílò èyí tíí ṣe `name` i.e. `orúkọ` tí ó yẹ kí ó jẹ́ `str`.
|
||||
* Ṣàyẹ̀wò pé ó ní àbùdá tí ó nílò èyí tíí ṣe `price` i.e. `iye` tí ó gbọ́dọ̀ jẹ́ `float`.
|
||||
* Ṣàyẹ̀wò pé ó ní àbùdá àṣàyàn `is_offer`, tí ó yẹ kí ó jẹ́ `bool`, tí ó bá wà níbẹ̀.
|
||||
* Gbogbo èyí yóò tún ṣiṣẹ́ fún àwọn ohun èlò JSON tí ó jìn gidi gan-an.
|
||||
* Yìí padà láti àti sí JSON lai fi ọwọ́ yi.
|
||||
* Ṣe àkọsílẹ̀ ohun gbogbo pẹ̀lú OpenAPI, èyí tí yóò wà ní lílo nípaṣẹ̀:
|
||||
* Àwọn ètò àkọsílẹ̀ ìbáṣepọ̀.
|
||||
* Aládàáṣiṣẹ́ oníbárà èlètò tíí ṣẹ̀dá kóòdù, fún ọ̀pọ̀lọpọ̀ àwọn èdè.
|
||||
* Pese àkọsílẹ̀ òní ìbáṣepọ̀ ti àwọn àgbékalẹ̀ ayélujára méjì tààrà.
|
||||
|
||||
---
|
||||
|
||||
A ń ṣẹ̀ṣẹ̀ ń mú ẹyẹ bọ́ làpò ní, ṣùgbọ́n ó ti ni òye bí gbogbo rẹ̀ ṣe ń ṣiṣẹ́.
|
||||
|
||||
Gbiyanju láti yí ìlà padà pẹ̀lú:
|
||||
|
||||
```Python
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
...láti:
|
||||
|
||||
```Python
|
||||
... "item_name": item.name ...
|
||||
```
|
||||
|
||||
...ṣí:
|
||||
|
||||
```Python
|
||||
... "item_price": item.price ...
|
||||
```
|
||||
|
||||
.. kí o sì wo bí olóòtú rẹ yóò ṣe parí àwọn àbùdá náà fúnra rẹ̀, yóò sì mọ irúfẹ́ wọn:
|
||||
|
||||

|
||||
|
||||
Fún àpẹẹrẹ pípé síi pẹ̀lú àwọn àbùdá mìíràn, wo <a href="https://fastapi.tiangolo.com/tutorial/">Ìdánilẹ́kọ̀ọ́ - Ìtọ́sọ́nà Olùmúlò</a>.
|
||||
|
||||
**Itaniji gẹ́gẹ́ bí isọ'ye**: ìdánilẹ́kọ̀ọ́ - itọsọna olùmúlò pẹ̀lú:
|
||||
|
||||
* Ìkéde àṣàyàn **pàrámítà** láti àwọn oriṣiriṣi ibòmíràn gẹ́gẹ́ bíi: àwọn **àkọlé èsì API**, **kúkì**, **ààyè fọọmu**, àti **fáìlì**.
|
||||
* Bíi ó ṣe lé ṣètò **àwọn ìdíwọ́ ìfọwọ́sí** bí `maximum_length` tàbí `regex`.
|
||||
* Ó lágbára púpọ̀ ó sì rọrùn láti lo ètò **<abbr title="a tún mọ̀ sí ìrìnṣẹ́, àwọn ohun àmúlò iṣẹ́, olupese, àwọn ohun àfikún ">Àfikún Ìgbẹ́kẹ̀lé Kóòdù</abbr>**.
|
||||
* Ààbò àti ìfọwọ́sowọ́pọ̀, pẹ̀lú àtìlẹ́yìn fún **OAuth2** pẹ̀lú **àmì JWT** àti **HTTP Ipilẹ ìfọwọ́sowọ́pọ̀**.
|
||||
* Àwọn ìlànà ìlọsíwájú (ṣùgbọ́n tí ó rọrùn bákan náà) fún ìkéde **àwọn àwòṣe JSON tó jinlẹ̀** (ọpẹ́ pàtàkìsi sí Pydantic).
|
||||
* Iṣọpọ **GraphQL** pẹ̀lú <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> àti àwọn ohun èlò ìwé kóòdù afọwọkọ mìíràn tí kò yí padà.
|
||||
* Ọpọlọpọ àwọn àfikún àwọn ẹ̀yà (ọpẹ́ pàtàkìsi sí Starlette) bí:
|
||||
* **WebSockets**
|
||||
* àwọn ìdánwò tí ó rọrùn púpọ̀ lórí HTTPX àti `pytest`
|
||||
* **CORS**
|
||||
* **Cookie Sessions**
|
||||
* ...àti síwájú síi.
|
||||
|
||||
## Ìṣesí
|
||||
|
||||
Àwọn àlá TechEmpower fi hàn pé **FastAPI** ń ṣiṣẹ́ lábẹ́ Uvicorn gẹ́gẹ́ bí <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">ọ̀kan lára àwọn ìlànà Python tí ó yára jùlọ tí ó wà</a>, ní ìsàlẹ̀ Starlette àti Uvicorn fúnra wọn (tí FastAPI ń lò fúnra rẹ̀). (*)
|
||||
|
||||
Láti ní òye síi nípa rẹ̀, wo abala àwọn <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Àlá</a>.
|
||||
|
||||
## Àṣàyàn Àwọn Àfikún Ìgbẹ́kẹ̀lé Kóòdù
|
||||
|
||||
Èyí tí Pydantic ń lò:
|
||||
|
||||
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - fún ifọwọsi ímeèlì.
|
||||
* <a href="https://docs.pydantic.dev/latest/usage/pydantic_settings/" target="_blank"><code>pydantic-settings</code></a> - fún ètò ìsàkóso.
|
||||
* <a href="https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/" target="_blank"><code>pydantic-extra-types</code></a> - fún àfikún oríṣi láti lọ pẹ̀lú Pydantic.
|
||||
|
||||
Èyí tí Starlette ń lò:
|
||||
|
||||
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Nílò tí ó bá fẹ́ láti lọ `TestClient`.
|
||||
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Nílò tí ó bá fẹ́ láti lọ iṣeto awoṣe aiyipada.
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Nílò tí ó bá fẹ́ láti ṣe àtìlẹ́yìn fún <abbr title="tí ó se ìyípadà ọ̀rọ̀-ìyọ̀/òkun-ọ̀rọ̀ tí ó wà láti ìbéèrè HTTP sí inú àkójọf'áyẹ̀wò Python">"àyẹ̀wò"</abbr> fọọmu, pẹ̀lú `request.form()`.
|
||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Nílò fún àtìlẹ́yìn `SessionMiddleware`.
|
||||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Nílò fún àtìlẹ́yìn Starlette's `SchemaGenerator` (ó ṣe ṣe kí ó má nílò rẹ̀ fún FastAPI).
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Nílò tí ó bá fẹ́ láti lọ `UJSONResponse`.
|
||||
|
||||
Èyí tí FastAPI / Starlette ń lò:
|
||||
|
||||
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - Fún olupin tí yóò sẹ́ àmúyẹ àti tí yóò ṣe ìpèsè fún iṣẹ́ rẹ tàbí ohun èlò rẹ.
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Nílò tí ó bá fẹ́ láti lọ `ORJSONResponse`.
|
||||
|
||||
Ó lè fi gbogbo àwọn wọ̀nyí sórí ẹrọ pẹ̀lú `pip install "fastapi[all]"`.
|
||||
|
||||
## Iwe-aṣẹ
|
||||
|
||||
Iṣẹ́ yìí ni iwe-aṣẹ lábẹ́ àwọn òfin tí iwe-aṣẹ MIT.
|
||||
1
docs/yo/mkdocs.yml
Normal file
1
docs/yo/mkdocs.yml
Normal file
@@ -0,0 +1 @@
|
||||
INHERIT: ../en/mkdocs.yml
|
||||
266
docs/zh/docs/advanced/generate-clients.md
Normal file
266
docs/zh/docs/advanced/generate-clients.md
Normal file
@@ -0,0 +1,266 @@
|
||||
# 生成客户端
|
||||
|
||||
因为 **FastAPI** 是基于OpenAPI规范的,自然您可以使用许多相匹配的工具,包括自动生成API文档 (由 Swagger UI 提供)。
|
||||
|
||||
一个不太明显而又特别的优势是,你可以为你的API针对不同的**编程语言**来**生成客户端**(有时候被叫做 <abbr title="Software Development Kits">**SDKs**</abbr> )。
|
||||
|
||||
## OpenAPI 客户端生成
|
||||
|
||||
有许多工具可以从**OpenAPI**生成客户端。
|
||||
|
||||
一个常见的工具是 <a href="https://openapi-generator.tech/" class="external-link" target="_blank">OpenAPI Generator</a>。
|
||||
|
||||
如果您正在开发**前端**,一个非常有趣的替代方案是 <a href="https://github.com/ferdikoomen/openapi-typescript-codegen" class="external-link" target="_blank">openapi-typescript-codegen</a>。
|
||||
|
||||
## 生成一个 TypeScript 前端客户端
|
||||
|
||||
让我们从一个简单的 FastAPI 应用开始:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="7-9 12-13 16-17 21"
|
||||
{!> ../../../docs_src/generate_clients/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="9-11 14-15 18 19 23"
|
||||
{!> ../../../docs_src/generate_clients/tutorial001.py!}
|
||||
```
|
||||
|
||||
请注意,*路径操作* 定义了他们所用于请求数据和回应数据的模型,所使用的模型是`Item` 和 `ResponseMessage`。
|
||||
|
||||
### API 文档
|
||||
|
||||
如果您访问API文档,您将看到它具有在请求中发送和在响应中接收数据的**模式(schemas)**:
|
||||
|
||||
<img src="/img/tutorial/generate-clients/image01.png">
|
||||
|
||||
您可以看到这些模式,因为它们是用程序中的模型声明的。
|
||||
|
||||
那些信息可以在应用的 **OpenAPI模式** 被找到,然后显示在API文档中(通过Swagger UI)。
|
||||
|
||||
OpenAPI中所包含的模型里有相同的信息可以用于 **生成客户端代码**。
|
||||
|
||||
### 生成一个TypeScript 客户端
|
||||
|
||||
现在我们有了带有模型的应用,我们可以为前端生成客户端代码。
|
||||
|
||||
#### 安装 `openapi-typescript-codegen`
|
||||
|
||||
您可以使用以下工具在前端代码中安装 `openapi-typescript-codegen`:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ npm install openapi-typescript-codegen --save-dev
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
#### 生成客户端代码
|
||||
|
||||
要生成客户端代码,您可以使用现在将要安装的命令行应用程序 `openapi`。
|
||||
|
||||
因为它安装在本地项目中,所以您可能无法直接使用此命令,但您可以将其放在 `package.json` 文件中。
|
||||
|
||||
它可能看起来是这样的:
|
||||
|
||||
```JSON hl_lines="7"
|
||||
{
|
||||
"name": "frontend-app",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"generate-client": "openapi --input http://localhost:8000/openapi.json --output ./src/client --client axios"
|
||||
},
|
||||
"author": "",
|
||||
"license": "",
|
||||
"devDependencies": {
|
||||
"openapi-typescript-codegen": "^0.20.1",
|
||||
"typescript": "^4.6.2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
在这里添加 NPM `generate-client` 脚本后,您可以使用以下命令运行它:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ npm run generate-client
|
||||
|
||||
frontend-app@1.0.0 generate-client /home/user/code/frontend-app
|
||||
> openapi --input http://localhost:8000/openapi.json --output ./src/client --client axios
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
此命令将在 `./src/client` 中生成代码,并将在其内部使用 `axios`(前端HTTP库)。
|
||||
|
||||
### 尝试客户端代码
|
||||
|
||||
现在您可以导入并使用客户端代码,它可能看起来像这样,请注意,您可以为这些方法使用自动补全:
|
||||
|
||||
<img src="/img/tutorial/generate-clients/image02.png">
|
||||
|
||||
您还将自动补全要发送的数据:
|
||||
|
||||
<img src="/img/tutorial/generate-clients/image03.png">
|
||||
|
||||
!!! tip
|
||||
请注意, `name` 和 `price` 的自动补全,是通过其在`Item`模型(FastAPI)中的定义实现的。
|
||||
|
||||
如果发送的数据字段不符,你也会看到编辑器的错误提示:
|
||||
|
||||
<img src="/img/tutorial/generate-clients/image04.png">
|
||||
|
||||
响应(response)对象也拥有自动补全:
|
||||
|
||||
<img src="/img/tutorial/generate-clients/image05.png">
|
||||
|
||||
## 带有标签的 FastAPI 应用
|
||||
|
||||
在许多情况下,你的FastAPI应用程序会更复杂,你可能会使用标签来分隔不同组的*路径操作(path operations)*。
|
||||
|
||||
例如,您可以有一个用 `items` 的部分和另一个用于 `users` 的部分,它们可以用标签来分隔:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="21 26 34"
|
||||
{!> ../../../docs_src/generate_clients/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="23 28 36"
|
||||
{!> ../../../docs_src/generate_clients/tutorial002.py!}
|
||||
```
|
||||
|
||||
### 生成带有标签的 TypeScript 客户端
|
||||
|
||||
如果您使用标签为FastAPI应用生成客户端,它通常也会根据标签分割客户端代码。
|
||||
|
||||
通过这种方式,您将能够为客户端代码进行正确地排序和分组:
|
||||
|
||||
<img src="/img/tutorial/generate-clients/image06.png">
|
||||
|
||||
在这个案例中,您有:
|
||||
|
||||
* `ItemsService`
|
||||
* `UsersService`
|
||||
|
||||
### 客户端方法名称
|
||||
|
||||
现在生成的方法名像 `createItemItemsPost` 看起来不太简洁:
|
||||
|
||||
```TypeScript
|
||||
ItemsService.createItemItemsPost({name: "Plumbus", price: 5})
|
||||
```
|
||||
|
||||
...这是因为客户端生成器为每个 *路径操作* 使用OpenAPI的内部 **操作 ID(operation ID)**。
|
||||
|
||||
OpenAPI要求每个操作 ID 在所有 *路径操作* 中都是唯一的,因此 FastAPI 使用**函数名**、**路径**和**HTTP方法/操作**来生成此操作ID,因为这样可以确保这些操作 ID 是唯一的。
|
||||
|
||||
但接下来我会告诉你如何改进。 🤓
|
||||
|
||||
## 自定义操作ID和更好的方法名
|
||||
|
||||
您可以**修改**这些操作ID的**生成**方式,以使其更简洁,并在客户端中具有**更简洁的方法名称**。
|
||||
|
||||
在这种情况下,您必须确保每个操作ID在其他方面是**唯一**的。
|
||||
|
||||
例如,您可以确保每个*路径操作*都有一个标签,然后根据**标签**和*路径操作***名称**(函数名)来生成操作ID。
|
||||
|
||||
### 自定义生成唯一ID函数
|
||||
|
||||
FastAPI为每个*路径操作*使用一个**唯一ID**,它用于**操作ID**,也用于任何所需自定义模型的名称,用于请求或响应。
|
||||
|
||||
你可以自定义该函数。它接受一个 `APIRoute` 对象作为输入,并输出一个字符串。
|
||||
|
||||
例如,以下是一个示例,它使用第一个标签(你可能只有一个标签)和*路径操作*名称(函数名)。
|
||||
|
||||
然后,你可以将这个自定义函数作为 `generate_unique_id_function` 参数传递给 **FastAPI**:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="6-7 10"
|
||||
{!> ../../../docs_src/generate_clients/tutorial003_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="8-9 12"
|
||||
{!> ../../../docs_src/generate_clients/tutorial003.py!}
|
||||
```
|
||||
|
||||
### 使用自定义操作ID生成TypeScript客户端
|
||||
|
||||
现在,如果你再次生成客户端,你会发现它具有改善的方法名称:
|
||||
|
||||
<img src="/img/tutorial/generate-clients/image07.png">
|
||||
|
||||
正如你所见,现在方法名称中只包含标签和函数名,不再包含URL路径和HTTP操作的信息。
|
||||
|
||||
### 预处理用于客户端生成器的OpenAPI规范
|
||||
|
||||
生成的代码仍然存在一些**重复的信息**。
|
||||
|
||||
我们已经知道该方法与 **items** 相关,因为它在 `ItemsService` 中(从标签中获取),但方法名中仍然有标签名作为前缀。😕
|
||||
|
||||
一般情况下对于OpenAPI,我们可能仍然希望保留它,因为这将确保操作ID是**唯一的**。
|
||||
|
||||
但对于生成的客户端,我们可以在生成客户端之前**修改** OpenAPI 操作ID,以使方法名称更加美观和**简洁**。
|
||||
|
||||
我们可以将 OpenAPI JSON 下载到一个名为`openapi.json`的文件中,然后使用以下脚本**删除此前缀的标签**:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/generate_clients/tutorial004.py!}
|
||||
```
|
||||
|
||||
通过这样做,操作ID将从类似于 `items-get_items` 的名称重命名为 `get_items` ,这样客户端生成器就可以生成更简洁的方法名称。
|
||||
|
||||
### 使用预处理的OpenAPI生成TypeScript客户端
|
||||
|
||||
现在,由于最终结果保存在文件openapi.json中,你可以修改 package.json 文件以使用此本地文件,例如:
|
||||
|
||||
```JSON hl_lines="7"
|
||||
{
|
||||
"name": "frontend-app",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"generate-client": "openapi --input ./openapi.json --output ./src/client --client axios"
|
||||
},
|
||||
"author": "",
|
||||
"license": "",
|
||||
"devDependencies": {
|
||||
"openapi-typescript-codegen": "^0.20.1",
|
||||
"typescript": "^4.6.2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
生成新的客户端之后,你现在将拥有**清晰的方法名称**,具备**自动补全**、**错误提示**等功能:
|
||||
|
||||
<img src="/img/tutorial/generate-clients/image08.png">
|
||||
|
||||
## 优点
|
||||
|
||||
当使用自动生成的客户端时,你将获得以下的自动补全功能:
|
||||
|
||||
* 方法。
|
||||
* 请求体中的数据、查询参数等。
|
||||
* 响应数据。
|
||||
|
||||
你还将获得针对所有内容的错误提示。
|
||||
|
||||
每当你更新后端代码并**重新生成**前端代码时,新的*路径操作*将作为方法可用,旧的方法将被删除,并且其他任何更改将反映在生成的代码中。 🤓
|
||||
|
||||
这也意味着如果有任何更改,它将自动**反映**在客户端代码中。如果你**构建**客户端,在使用的数据上存在**不匹配**时,它将报错。
|
||||
|
||||
因此,你将在开发周期的早期**检测到许多错误**,而不必等待错误在生产环境中向最终用户展示,然后尝试调试问题所在。 ✨
|
||||
430
docs/zh/docs/async.md
Normal file
430
docs/zh/docs/async.md
Normal file
@@ -0,0 +1,430 @@
|
||||
# 并发 async / await
|
||||
|
||||
有关路径操作函数的 `async def` 语法以及异步代码、并发和并行的一些背景知识。
|
||||
|
||||
## 赶时间吗?
|
||||
|
||||
<abbr title="too long; didn't read(长文警告)"><strong>TL;DR:</strong></abbr>
|
||||
|
||||
如果你正在使用第三方库,它们会告诉你使用 `await` 关键字来调用它们,就像这样:
|
||||
|
||||
```Python
|
||||
results = await some_library()
|
||||
```
|
||||
|
||||
然后,通过 `async def` 声明你的 *路径操作函数*:
|
||||
|
||||
```Python hl_lines="2"
|
||||
@app.get('/')
|
||||
async def read_results():
|
||||
results = await some_library()
|
||||
return results
|
||||
```
|
||||
|
||||
!!! note
|
||||
你只能在被 `async def` 创建的函数内使用 `await`
|
||||
|
||||
---
|
||||
|
||||
如果你正在使用一个第三方库和某些组件(比如:数据库、API、文件系统...)进行通信,第三方库又不支持使用 `await` (目前大多数数据库三方库都是这样),这种情况你可以像平常那样使用 `def` 声明一个路径操作函数,就像这样:
|
||||
|
||||
```Python hl_lines="2"
|
||||
@app.get('/')
|
||||
def results():
|
||||
results = some_library()
|
||||
return results
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
如果你的应用程序不需要与其他任何东西通信而等待其响应,请使用 `async def`。
|
||||
|
||||
---
|
||||
|
||||
如果你不清楚,使用 `def` 就好.
|
||||
|
||||
---
|
||||
|
||||
**注意**:你可以根据需要在路径操作函数中混合使用 `def` 和 `async def`,并使用最适合你的方式去定义每个函数。FastAPI 将为他们做正确的事情。
|
||||
|
||||
无论如何,在上述任何情况下,FastAPI 仍将异步工作,速度也非常快。
|
||||
|
||||
但是,通过遵循上述步骤,它将能够进行一些性能优化。
|
||||
|
||||
## 技术细节
|
||||
|
||||
Python 的现代版本支持通过一种叫**"协程"**——使用 `async` 和 `await` 语法的东西来写**”异步代码“**。
|
||||
|
||||
让我们在下面的部分中逐一介绍:
|
||||
|
||||
* **异步代码**
|
||||
* **`async` 和 `await`**
|
||||
* **协程**
|
||||
|
||||
## 异步代码
|
||||
|
||||
异步代码仅仅意味着编程语言 💬 有办法告诉计算机/程序 🤖 在代码中的某个点,它 🤖 将不得不等待在某些地方完成一些事情。让我们假设一些事情被称为 "慢文件"📝.
|
||||
|
||||
所以,在等待"慢文件"📝完成的这段时间,计算机可以做一些其他工作。
|
||||
|
||||
然后计算机/程序 🤖 每次有机会都会回来,因为它又在等待,或者它 🤖 完成了当前所有的工作。而且它 🤖 将查看它等待的所有任务中是否有已经完成的,做它必须做的任何事情。
|
||||
|
||||
接下来,它 🤖 完成第一个任务(比如是我们的"慢文件"📝) 并继续与之相关的一切。
|
||||
|
||||
这个"等待其他事情"通常指的是一些相对较慢(与处理器和 RAM 存储器的速度相比)的 <abbr title="Input and Output">I/O</abbr> 操作,比如说:
|
||||
|
||||
* 通过网络发送来自客户端的数据
|
||||
* 客户端接收来自网络中的数据
|
||||
* 磁盘中要由系统读取并提供给程序的文件的内容
|
||||
* 程序提供给系统的要写入磁盘的内容
|
||||
* 一个 API 的远程调用
|
||||
* 一个数据库操作,直到完成
|
||||
* 一个数据库查询,直到返回结果
|
||||
* 等等.
|
||||
|
||||
这个执行的时间大多是在等待 <abbr title="Input and Output">I/O</abbr> 操作,因此它们被叫做 "I/O 密集型" 操作。
|
||||
|
||||
它被称为"异步"的原因是因为计算机/程序不必与慢任务"同步",去等待任务完成的确切时刻,而在此期间不做任何事情直到能够获取任务结果才继续工作。
|
||||
|
||||
相反,作为一个"异步"系统,一旦完成,任务就可以排队等待一段时间(几微秒),等待计算机程序完成它要做的任何事情,然后回来获取结果并继续处理它们。
|
||||
|
||||
对于"同步"(与"异步"相反),他们通常也使用"顺序"一词,因为计算机程序在切换到另一个任务之前是按顺序执行所有步骤,即使这些步骤涉及到等待。
|
||||
|
||||
### 并发与汉堡
|
||||
|
||||
上述异步代码的思想有时也被称为“并发”,它不同于“并行”。
|
||||
|
||||
并发和并行都与“不同的事情或多或少同时发生”有关。
|
||||
|
||||
但是并发和并行之间的细节是完全不同的。
|
||||
|
||||
要了解差异,请想象以下关于汉堡的故事:
|
||||
|
||||
### 并发汉堡
|
||||
|
||||
你和你的恋人一起去快餐店,你排队在后面,收银员从你前面的人接单。😍
|
||||
|
||||
<img src="/img/async/concurrent-burgers/concurrent-burgers-01.png" class="illustration">
|
||||
|
||||
然后轮到你了,你为你的恋人和你选了两个非常豪华的汉堡。🍔🍔
|
||||
|
||||
<img src="/img/async/concurrent-burgers/concurrent-burgers-02.png" class="illustration">
|
||||
|
||||
收银员对厨房里的厨师说了一些话,让他们知道他们必须为你准备汉堡(尽管他们目前正在为之前的顾客准备汉堡)。
|
||||
|
||||
<img src="/img/async/concurrent-burgers/concurrent-burgers-03.png" class="illustration">
|
||||
|
||||
你付钱了。 💸
|
||||
|
||||
收银员给你轮到的号码。
|
||||
|
||||
<img src="/img/async/concurrent-burgers/concurrent-burgers-04.png" class="illustration">
|
||||
|
||||
当你在等待的时候,你和你的恋人一起去挑选一张桌子,然后你们坐下来聊了很长时间(因为汉堡很豪华,需要一些时间来准备)。
|
||||
|
||||
当你和你的恋人坐在桌子旁,等待汉堡的时候,你可以用这段时间来欣赏你的恋人是多么的棒、可爱和聪明✨😍✨。
|
||||
|
||||
<img src="/img/async/concurrent-burgers/concurrent-burgers-05.png" class="illustration">
|
||||
|
||||
在等待中和你的恋人交谈时,你会不时地查看柜台上显示的号码,看看是否已经轮到你了。
|
||||
|
||||
然后在某个时刻,终于轮到你了。你去柜台拿汉堡然后回到桌子上。
|
||||
|
||||
<img src="/img/async/concurrent-burgers/concurrent-burgers-06.png" class="illustration">
|
||||
|
||||
你们享用了汉堡,整个过程都很开心。✨
|
||||
|
||||
<img src="/img/async/concurrent-burgers/concurrent-burgers-07.png" class="illustration">
|
||||
|
||||
!!! info
|
||||
漂亮的插画来自 <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a>. 🎨
|
||||
|
||||
---
|
||||
|
||||
在那个故事里,假设你是计算机程序 🤖 。
|
||||
|
||||
当你在排队时,你只是闲着😴, 轮到你前不做任何事情(仅排队)。但排队很快,因为收银员只接订单(不准备订单),所以这一切都还好。
|
||||
|
||||
然后,当轮到你时,需要你做一些实际性的工作,比如查看菜单,决定你想要什么,让你的恋人选择,支付,检查你是否提供了正确的账单或卡,检查你的收费是否正确,检查订单是否有正确的项目,等等。
|
||||
|
||||
此时,即使你仍然没有汉堡,你和收银员的工作也"暂停"了⏸, 因为你必须等待一段时间 🕙 让你的汉堡做好。
|
||||
|
||||
但是,当你离开柜台并坐在桌子旁,在轮到你的号码前的这段时间,你可以将焦点切换到 🔀 你的恋人上,并做一些"工作"⏯ 🤓。你可以做一些非常"有成效"的事情,比如和你的恋人调情😍.
|
||||
|
||||
之后,收银员 💁 把号码显示在显示屏上,并说到 "汉堡做好了",而当显示的号码是你的号码时,你不会立刻疯狂地跳起来。因为你知道没有人会偷你的汉堡,因为你有你的号码,而其他人又有他们自己的号码。
|
||||
|
||||
所以你要等待你的恋人完成故事(完成当前的工作⏯ /正在做的事🤓), 轻轻微笑,说你要吃汉堡⏸.
|
||||
|
||||
然后你去柜台🔀, 到现在初始任务已经完成⏯, 拿起汉堡,说声谢谢,然后把它们送到桌上。这就完成了与计数器交互的步骤/任务⏹. 这反过来又产生了一项新任务,即"吃汉堡"🔀 ⏯, 上一个"拿汉堡"的任务已经结束了⏹.
|
||||
|
||||
### 并行汉堡
|
||||
|
||||
现在让我们假设不是"并发汉堡",而是"并行汉堡"。
|
||||
|
||||
你和你的恋人一起去吃并行快餐。
|
||||
|
||||
你站在队伍中,同时是厨师的几个收银员(比方说8个)从前面的人那里接单。
|
||||
|
||||
你之前的每个人都在等待他们的汉堡准备好后才离开柜台,因为8名收银员都会在下一份订单前马上准备好汉堡。
|
||||
|
||||
<img src="/img/async/parallel-burgers/parallel-burgers-01.png" class="illustration">
|
||||
|
||||
然后,终于轮到你了,你为你的恋人和你订购了两个非常精美的汉堡。
|
||||
|
||||
你付钱了 💸。
|
||||
|
||||
<img src="/img/async/parallel-burgers/parallel-burgers-02.png" class="illustration">
|
||||
|
||||
收银员去厨房。
|
||||
|
||||
你站在柜台前 🕙等待着,这样就不会有人在你之前抢走你的汉堡,因为没有轮流的号码。
|
||||
|
||||
<img src="/img/async/parallel-burgers/parallel-burgers-03.png" class="illustration">
|
||||
|
||||
当你和你的恋人忙于不让任何人出现在你面前,并且在他们到来的时候拿走你的汉堡时,你无法关注到你的恋人。😞
|
||||
|
||||
这是"同步"的工作,你被迫与服务员/厨师 👨🍳"同步"。你在此必须等待 🕙 ,在收银员/厨师 👨🍳 完成汉堡并将它们交给你的确切时间到达之前一直等待,否则其他人可能会拿走它们。
|
||||
|
||||
<img src="/img/async/parallel-burgers/parallel-burgers-04.png" class="illustration">
|
||||
|
||||
你经过长时间的等待 🕙 ,收银员/厨师 👨🍳终于带着汉堡回到了柜台。
|
||||
|
||||
<img src="/img/async/parallel-burgers/parallel-burgers-05.png" class="illustration">
|
||||
|
||||
你拿着汉堡,和你的情人一起上桌。
|
||||
|
||||
你们仅仅是吃了它们,就结束了。⏹
|
||||
|
||||
<img src="/img/async/parallel-burgers/parallel-burgers-06.png" class="illustration">
|
||||
|
||||
没有太多的交谈或调情,因为大部分时间 🕙 都在柜台前等待😞。
|
||||
|
||||
!!! info
|
||||
漂亮的插画来自 <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a>. 🎨
|
||||
|
||||
---
|
||||
|
||||
在这个并行汉堡的场景中,你是一个计算机程序 🤖 且有两个处理器(你和你的恋人),都在等待 🕙 ,并投入他们的注意力 ⏯ 在柜台上等待了很长一段时间。
|
||||
|
||||
这家快餐店有 8 个处理器(收银员/厨师)。而并发汉堡店可能只有 2 个(一个收银员和一个厨师)。
|
||||
|
||||
但最终的体验仍然不是最好的。😞
|
||||
|
||||
---
|
||||
|
||||
这将是与汉堡的类似故事。🍔
|
||||
|
||||
一种更"贴近生活"的例子,想象一家银行。
|
||||
|
||||
直到最近,大多数银行都有多个出纳员 👨💼👨💼👨💼👨💼 还有一条长长排队队伍🕙🕙🕙🕙🕙🕙🕙🕙。
|
||||
|
||||
所有收银员都是一个接一个的在客户面前做完所有的工作👨💼⏯.
|
||||
|
||||
你必须经过 🕙 较长时间排队,否则你就没机会了。
|
||||
|
||||
你可不会想带你的恋人 😍 和你一起去银行办事🏦.
|
||||
|
||||
### 汉堡结论
|
||||
|
||||
在"你与恋人一起吃汉堡"的这个场景中,因为有很多人在等待🕙, 使用并发系统更有意义⏸🔀⏯.
|
||||
|
||||
大多数 Web 应用都是这样的。
|
||||
|
||||
你的服务器正在等待很多很多用户通过他们不太好的网络发送来的请求。
|
||||
|
||||
然后再次等待 🕙 响应回来。
|
||||
|
||||
这个"等待" 🕙 是以微秒为单位测量的,但总的来说,最后还是等待很久。
|
||||
|
||||
这就是为什么使用异步对于 Web API 很有意义的原因 ⏸🔀⏯。
|
||||
|
||||
这种异步机制正是 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](deployment/index.md){.internal-link target=_blank}。
|
||||
|
||||
## `async` 和 `await`
|
||||
|
||||
现代版本的 Python 有一种非常直观的方式来定义异步代码。这使它看起来就像正常的"顺序"代码,并在适当的时候"等待"。
|
||||
|
||||
当有一个操作需要等待才能给出结果,且支持这个新的 Python 特性时,您可以编写如下代码:
|
||||
|
||||
```Python
|
||||
burgers = await get_burgers(2)
|
||||
```
|
||||
|
||||
这里的关键是 `await`。它告诉 Python 它必须等待 ⏸ `get_burgers(2)` 完成它的工作 🕙 ,然后将结果存储在 `burgers` 中。这样,Python 就会知道此时它可以去做其他事情 🔀 ⏯ (比如接收另一个请求)。
|
||||
|
||||
要使 `await` 工作,它必须位于支持这种异步机制的函数内。因此,只需使用 `async def` 声明它:
|
||||
|
||||
```Python hl_lines="1"
|
||||
async def get_burgers(number: int):
|
||||
# Do some asynchronous stuff to create the burgers
|
||||
return burgers
|
||||
```
|
||||
|
||||
...而不是 `def`:
|
||||
|
||||
```Python hl_lines="2"
|
||||
# This is not asynchronous
|
||||
def get_sequential_burgers(number: int):
|
||||
# Do some sequential stuff to create the burgers
|
||||
return burgers
|
||||
```
|
||||
|
||||
使用 `async def`,Python 就知道在该函数中,它将遇上 `await`,并且它可以"暂停" ⏸ 执行该函数,直至执行其他操作 🔀 后回来。
|
||||
|
||||
当你想调用一个 `async def` 函数时,你必须"等待"它。因此,这不会起作用:
|
||||
|
||||
```Python
|
||||
# This won't work, because get_burgers was defined with: async def
|
||||
burgers = get_burgers(2)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
因此,如果您使用的库告诉您可以使用 `await` 调用它,则需要使用 `async def` 创建路径操作函数 ,如:
|
||||
|
||||
```Python hl_lines="2-3"
|
||||
@app.get('/burgers')
|
||||
async def read_burgers():
|
||||
burgers = await get_burgers(2)
|
||||
return burgers
|
||||
```
|
||||
|
||||
### 更多技术细节
|
||||
|
||||
您可能已经注意到,`await` 只能在 `async def` 定义的函数内部使用。
|
||||
|
||||
但与此同时,必须"等待"通过 `async def` 定义的函数。因此,带 `async def` 的函数也只能在 `async def` 定义的函数内部调用。
|
||||
|
||||
那么,这关于先有鸡还是先有蛋的问题,如何调用第一个 `async` 函数?
|
||||
|
||||
如果您使用 **FastAPI**,你不必担心这一点,因为"第一个"函数将是你的路径操作函数,FastAPI 将知道如何做正确的事情。
|
||||
|
||||
但如果您想在没有 FastAPI 的情况下使用 `async` / `await`,则可以这样做。
|
||||
|
||||
### 编写自己的异步代码
|
||||
|
||||
Starlette (和 **FastAPI**) 是基于 <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a> 实现的,这使得它们可以兼容 Python 的标准库 <a href="https://docs.python.org/3/library/asyncio-task.html" class="external-link" target="_blank">asyncio</a> 和 <a href="https://trio.readthedocs.io/en/stable/" class="external-link" target="_blank">Trio</a>。
|
||||
|
||||
特别是,你可以直接使用 <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a> 来处理高级的并发用例,这些用例需要在自己的代码中使用更高级的模式。
|
||||
|
||||
即使您没有使用 **FastAPI**,您也可以使用 <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</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` 函数返回的一个非常奇特的东西的称呼。Python 知道它有点像一个函数,它可以启动,也会在某个时刻结束,而且它可能会在内部暂停 ⏸ ,只要内部有一个 `await`。
|
||||
|
||||
通过使用 `async` 和 `await` 的异步代码的所有功能大多数被概括为"协程"。它可以与 Go 的主要关键特性 "Goroutines" 相媲美。
|
||||
|
||||
## 结论
|
||||
|
||||
让我们再来回顾下上文所说的:
|
||||
|
||||
> Python 的现代版本可以通过使用 `async` 和 `await` 语法创建**协程**,并用于支持**异步代码**。
|
||||
|
||||
现在应该能明白其含义了。✨
|
||||
|
||||
所有这些使得 FastAPI(通过 Starlette)如此强大,也是它拥有如此令人印象深刻的性能的原因。
|
||||
|
||||
## 非常技术性的细节
|
||||
|
||||
!!! warning
|
||||
你可以跳过这里。
|
||||
|
||||
这些都是 FastAPI 如何在内部工作的技术细节。
|
||||
|
||||
如果您有相当多的技术知识(协程、线程、阻塞等),并且对 FastAPI 如何处理 `async def` 与常规 `def` 感到好奇,请继续。
|
||||
|
||||
### 路径操作函数
|
||||
|
||||
当你使用 `def` 而不是 `async def` 来声明一个*路径操作函数*时,它运行在外部的线程池中并等待其结果,而不是直接调用(因为它会阻塞服务器)。
|
||||
|
||||
如果您使用过另一个不以上述方式工作的异步框架,并且您习惯于用普通的 `def` 定义普通的仅计算路径操作函数,以获得微小的性能增益(大约100纳秒),请注意,在 FastAPI 中,效果将完全相反。在这些情况下,最好使用 `async def`,除非路径操作函数内使用执行阻塞 <abbr title="输入/输出:磁盘读写,网络通讯.">I/O</abbr> 的代码。
|
||||
|
||||
在这两种情况下,与您之前的框架相比,**FastAPI** 可能[仍然很快](/#performance){.internal-link target=_blank}。
|
||||
|
||||
### 依赖
|
||||
|
||||
这同样适用于[依赖](/tutorial/dependencies/index.md){.internal-link target=_blank}。如果一个依赖是标准的 `def` 函数而不是 `async def`,它将被运行在外部线程池中。
|
||||
|
||||
### 子依赖
|
||||
|
||||
你可以拥有多个相互依赖的依赖以及[子依赖](/tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} (作为函数的参数),它们中的一些可能是通过 `async def` 声明,也可能是通过 `def` 声明。它们仍然可以正常工作,这些通过 `def` 声明的函数将会在外部线程中调用(来自线程池),而不是"被等待"。
|
||||
|
||||
### 其他函数
|
||||
|
||||
您可直接调用通过 `def` 或 `async def` 创建的任何其他函数,FastAPI 不会影响您调用它们的方式。
|
||||
|
||||
这与 FastAPI 为您调用*路径操作函数*和依赖项的逻辑相反。
|
||||
|
||||
如果你的函数是通过 `def` 声明的,它将被直接调用(在代码中编写的地方),而不会在线程池中,如果这个函数通过 `async def` 声明,当在代码中调用时,你就应该使用 `await` 等待函数的结果。
|
||||
|
||||
---
|
||||
|
||||
再次提醒,这些是非常技术性的细节,如果你来搜索它可能对你有用。
|
||||
|
||||
否则,您最好应该遵守的指导原则<a href="#_1">赶时间吗?</a>.
|
||||
87
docs/zh/docs/deployment/versions.md
Normal file
87
docs/zh/docs/deployment/versions.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# 关于 FastAPI 版本
|
||||
|
||||
**FastAPI** 已在许多应用程序和系统的生产环境中使用。 并且测试覆盖率保持在100%。 但其开发进度仍在快速推进。
|
||||
|
||||
经常添加新功能,定期修复错误,并且代码仍在持续改进。
|
||||
|
||||
这就是为什么当前版本仍然是`0.x.x`,这反映出每个版本都可能有Breaking changes。 这遵循<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.md){.internal-link target=_blank}中查看可用版本(例如查看当前最新版本)。
|
||||
|
||||
## 关于版本
|
||||
|
||||
遵循语义版本控制约定,任何低于`1.0.0`的版本都可能会添加 breaking changes。
|
||||
|
||||
FastAPI 还遵循这样的约定:任何`PATCH`版本更改都是为了bug修复和non-breaking changes。
|
||||
|
||||
!!! tip
|
||||
"PATCH"是最后一个数字,例如,在`0.2.3`中,PATCH版本是`3`。
|
||||
|
||||
因此,你应该能够固定到如下版本:
|
||||
|
||||
```txt
|
||||
fastapi>=0.45.0,<0.46.0
|
||||
```
|
||||
|
||||
"MINOR"版本中会添加breaking changes和新功能。
|
||||
|
||||
!!! tip
|
||||
"MINOR"是中间的数字,例如,在`0.2.3`中,MINOR版本是`2`。
|
||||
|
||||
## 升级FastAPI版本
|
||||
|
||||
你应该为你的应用程序添加测试。
|
||||
|
||||
使用 **FastAPI** 编写测试非常简单(感谢 Starlette),请参考文档:[测试](../tutorial/testing.md){.internal-link target=_blank}
|
||||
|
||||
添加测试后,你可以将 **FastAPI** 版本升级到更新版本,并通过运行测试来确保所有代码都能正常工作。
|
||||
|
||||
如果一切正常,或者在进行必要的更改之后,并且所有测试都通过了,那么你可以将`fastapi`固定到新的版本。
|
||||
|
||||
## 关于Starlette
|
||||
|
||||
你不应该固定`starlette`的版本。
|
||||
|
||||
不同版本的 **FastAPI** 将使用特定的较新版本的 Starlette。
|
||||
|
||||
因此,**FastAPI** 自己可以使用正确的 Starlette 版本。
|
||||
|
||||
## 关于 Pydantic
|
||||
|
||||
Pydantic 包含针对 **FastAPI** 的测试及其自己的测试,因此 Pydantic 的新版本(`1.0.0`以上)始终与 FastAPI 兼容。
|
||||
|
||||
你可以将 Pydantic 固定到适合你的`1.0.0`以上和`2.0.0`以下的任何版本。
|
||||
|
||||
例如:
|
||||
|
||||
````txt
|
||||
pydantic>=1.2.0,<2.0.0
|
||||
````
|
||||
@@ -1,94 +1,98 @@
|
||||
# 使用密码和 Bearer 的简单 OAuth2
|
||||
# OAuth2 实现简单的 Password 和 Bearer 验证
|
||||
|
||||
现在让我们接着上一章继续开发,并添加缺少的部分以实现一个完整的安全性流程。
|
||||
本章添加上一章示例中欠缺的部分,实现完整的安全流。
|
||||
|
||||
## 获取 `username` 和 `password`
|
||||
|
||||
我们将使用 **FastAPI** 的安全性实用工具来获取 `username` 和 `password`。
|
||||
首先,使用 **FastAPI** 安全工具获取 `username` 和 `password`。
|
||||
|
||||
OAuth2 规定在使用(我们打算用的)「password 流程」时,客户端/用户必须将 `username` 和 `password` 字段作为表单数据发送。
|
||||
OAuth2 规范要求使用**密码流**时,客户端或用户必须以表单数据形式发送 `username` 和 `password` 字段。
|
||||
|
||||
而且规范明确了字段必须这样命名。因此 `user-name` 或 `email` 是行不通的。
|
||||
并且,这两个字段必须命名为 `username` 和 `password` ,不能使用 `user-name` 或 `email` 等其它名称。
|
||||
|
||||
不过不用担心,你可以在前端按照你的想法将它展示给最终用户。
|
||||
不过也不用担心,前端仍可以显示终端用户所需的名称。
|
||||
|
||||
而且你的数据库模型也可以使用你想用的任何其他名称。
|
||||
数据库模型也可以使用所需的名称。
|
||||
|
||||
但是对于登录*路径操作*,我们需要使用这些名称来与规范兼容(以具备例如使用集成的 API 文档系统的能力)。
|
||||
但对于登录*路径操作*,则要使用兼容规范的 `username` 和 `password`,(例如,实现与 API 文档集成)。
|
||||
|
||||
规范还写明了 `username` 和 `password` 必须作为表单数据发送(因此,此处不能使用 JSON)。
|
||||
该规范要求必须以表单数据形式发送 `username` 和 `password`,因此,不能使用 JSON 对象。
|
||||
|
||||
### `scope`
|
||||
### `Scope`(作用域)
|
||||
|
||||
规范还提到客户端可以发送另一个表单字段「`scope`」。
|
||||
OAuth2 还支持客户端发送**`scope`**表单字段。
|
||||
|
||||
这个表单字段的名称为 `scope`(单数形式),但实际上它是一个由空格分隔的「作用域」组成的长字符串。
|
||||
虽然表单字段的名称是 `scope`(单数),但实际上,它是以空格分隔的,由多个**scope**组成的长字符串。
|
||||
|
||||
每个「作用域」只是一个字符串(中间没有空格)。
|
||||
**作用域**只是不带空格的字符串。
|
||||
|
||||
它们通常用于声明特定的安全权限,例如:
|
||||
常用于声明指定安全权限,例如:
|
||||
|
||||
* `users:read` 或者 `users:write` 是常见的例子。
|
||||
* Facebook / Instagram 使用 `instagram_basic`。
|
||||
* Google 使用了 `https://www.googleapis.com/auth/drive` 。
|
||||
* 常见用例为,`users:read` 或 `users:write`
|
||||
* 脸书和 Instagram 使用 `instagram_basic`
|
||||
* 谷歌使用 `https://www.googleapis.com/auth/drive`
|
||||
|
||||
!!! info
|
||||
在 OAuth2 中「作用域」只是一个声明所需特定权限的字符串。
|
||||
!!! info "说明"
|
||||
|
||||
它有没有 `:` 这样的其他字符或者是不是 URL 都没有关系。
|
||||
OAuth2 中,**作用域**只是声明指定权限的字符串。
|
||||
|
||||
这些细节是具体的实现。
|
||||
是否使用冒号 `:` 等符号,或是不是 URL 并不重要。
|
||||
|
||||
对 OAuth2 来说它们就只是字符串而已。
|
||||
这些细节只是特定的实现方式。
|
||||
|
||||
对 OAuth2 来说,都只是字符串而已。
|
||||
|
||||
## 获取 `username` 和 `password` 的代码
|
||||
|
||||
现在,让我们使用 **FastAPI** 提供的实用工具来处理此问题。
|
||||
接下来,使用 **FastAPI** 工具获取用户名与密码。
|
||||
|
||||
### `OAuth2PasswordRequestForm`
|
||||
|
||||
首先,导入 `OAuth2PasswordRequestForm`,然后在 `token` 的*路径操作*中通过 `Depends` 将其作为依赖项使用。
|
||||
首先,导入 `OAuth2PasswordRequestForm`,然后,在 `/token` *路径操作* 中,用 `Depends` 把该类作为依赖项。
|
||||
|
||||
```Python hl_lines="4 76"
|
||||
{!../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
`OAuth2PasswordRequestForm` 是一个类依赖项,声明了如下的请求表单:
|
||||
`OAuth2PasswordRequestForm` 是用以下几项内容声明表单请求体的类依赖项:
|
||||
|
||||
* `username`。
|
||||
* `password`。
|
||||
* 一个可选的 `scope` 字段,是一个由空格分隔的字符串组成的大字符串。
|
||||
* 一个可选的 `grant_type`.
|
||||
* `username`
|
||||
* `password`
|
||||
* 可选的 `scope` 字段,由多个空格分隔的字符串组成的长字符串
|
||||
* 可选的 `grant_type`
|
||||
|
||||
!!! tip
|
||||
OAuth2 规范实际上*要求* `grant_type` 字段使用一个固定的值 `password`,但是 `OAuth2PasswordRequestForm` 没有作强制约束。
|
||||
!!! tip "提示"
|
||||
|
||||
如果你需要强制要求这一点,请使用 `OAuth2PasswordRequestFormStrict` 而不是 `OAuth2PasswordRequestForm`。
|
||||
实际上,OAuth2 规范*要求* `grant_type` 字段使用固定值 `password`,但 `OAuth2PasswordRequestForm` 没有作强制约束。
|
||||
|
||||
* 一个可选的 `client_id`(我们的示例不需要它)。
|
||||
* 一个可选的 `client_secret`(我们的示例不需要它)。
|
||||
如需强制使用固定值 `password`,则不要用 `OAuth2PasswordRequestForm`,而是用 `OAuth2PasswordRequestFormStrict`。
|
||||
|
||||
!!! info
|
||||
`OAuth2PasswordRequestForm` 并不像 `OAuth2PasswordBearer` 一样是 FastAPI 的一个特殊的类。
|
||||
* 可选的 `client_id`(本例未使用)
|
||||
* 可选的 `client_secret`(本例未使用)
|
||||
|
||||
`OAuth2PasswordBearer` 使得 **FastAPI** 明白它是一个安全方案。所以它得以通过这种方式添加到 OpenAPI 中。
|
||||
!!! info "说明"
|
||||
|
||||
但 `OAuth2PasswordRequestForm` 只是一个你可以自己编写的类依赖项,或者你也可以直接声明 `Form` 参数。
|
||||
`OAuth2PasswordRequestForm` 与 `OAuth2PasswordBearer` 一样,都不是 FastAPI 的特殊类。
|
||||
|
||||
但是由于这是一种常见的使用场景,因此 FastAPI 出于简便直接提供了它。
|
||||
**FastAPI** 把 `OAuth2PasswordBearer` 识别为安全方案。因此,可以通过这种方式把它添加至 OpenAPI。
|
||||
|
||||
但 `OAuth2PasswordRequestForm` 只是可以自行编写的类依赖项,也可以直接声明 `Form` 参数。
|
||||
|
||||
但由于这种用例很常见,FastAPI 为了简便,就直接提供了对它的支持。
|
||||
|
||||
### 使用表单数据
|
||||
|
||||
!!! tip
|
||||
类依赖项 `OAuth2PasswordRequestForm` 的实例不会有用空格分隔的长字符串属性 `scope`,而是具有一个 `scopes` 属性,该属性将包含实际被发送的每个作用域字符串组成的列表。
|
||||
!!! tip "提示"
|
||||
|
||||
在此示例中我们没有使用 `scopes`,但如果你需要的话可以使用该功能。
|
||||
`OAuth2PasswordRequestForm` 类依赖项的实例没有以空格分隔的长字符串属性 `scope`,但它支持 `scopes` 属性,由已发送的 scope 字符串列表组成。
|
||||
|
||||
现在,使用表单字段中的 `username` 从(伪)数据库中获取用户数据。
|
||||
本例没有使用 `scopes`,但开发者也可以根据需要使用该属性。
|
||||
|
||||
如果没有这个用户,我们将返回一个错误消息,提示「用户名或密码错误」。
|
||||
现在,即可使用表单字段 `username`,从(伪)数据库中获取用户数据。
|
||||
|
||||
对于这个错误,我们使用 `HTTPException` 异常:
|
||||
如果不存在指定用户,则返回错误消息,提示**用户名或密码错误**。
|
||||
|
||||
本例使用 `HTTPException` 异常显示此错误:
|
||||
|
||||
```Python hl_lines="3 77-79"
|
||||
{!../../../docs_src/security/tutorial003.py!}
|
||||
@@ -96,27 +100,27 @@ OAuth2 规定在使用(我们打算用的)「password 流程」时,客户
|
||||
|
||||
### 校验密码
|
||||
|
||||
目前我们已经从数据库中获取了用户数据,但尚未校验密码。
|
||||
至此,我们已经从数据库中获取了用户数据,但尚未校验密码。
|
||||
|
||||
让我们首先将这些数据放入 Pydantic `UserInDB` 模型中。
|
||||
接下来,首先将数据放入 Pydantic 的 `UserInDB` 模型。
|
||||
|
||||
永远不要保存明文密码,因此,我们将使用(伪)哈希密码系统。
|
||||
注意:永远不要保存明文密码,本例暂时先使用(伪)哈希密码系统。
|
||||
|
||||
如果密码不匹配,我们将返回同一个错误。
|
||||
如果密码不匹配,则返回与上面相同的错误。
|
||||
|
||||
#### 哈希密码
|
||||
#### 密码哈希
|
||||
|
||||
「哈希」的意思是:将某些内容(在本例中为密码)转换为看起来像乱码的字节序列(只是一个字符串)。
|
||||
**哈希**是指,将指定内容(本例中为密码)转换为形似乱码的字节序列(其实就是字符串)。
|
||||
|
||||
每次你传入完全相同的内容(完全相同的密码)时,你都会得到完全相同的乱码。
|
||||
每次传入完全相同的内容(比如,完全相同的密码)时,得到的都是完全相同的乱码。
|
||||
|
||||
但是你不能从乱码转换回密码。
|
||||
但这个乱码无法转换回传入的密码。
|
||||
|
||||
##### 为什么使用哈希密码
|
||||
##### 为什么使用密码哈希
|
||||
|
||||
如果你的数据库被盗,小偷将无法获得用户的明文密码,只有哈希值。
|
||||
原因很简单,假如数据库被盗,窃贼无法获取用户的明文密码,得到的只是哈希值。
|
||||
|
||||
因此,小偷将无法尝试在另一个系统中使用这些相同的密码(由于许多用户在任何地方都使用相同的密码,因此这很危险)。
|
||||
这样一来,窃贼就无法在其它应用中使用窃取的密码,要知道,很多用户在所有系统中都使用相同的密码,风险超大。
|
||||
|
||||
```Python hl_lines="80-83"
|
||||
{!../../../docs_src/security/tutorial003.py!}
|
||||
@@ -124,9 +128,9 @@ OAuth2 规定在使用(我们打算用的)「password 流程」时,客户
|
||||
|
||||
#### 关于 `**user_dict`
|
||||
|
||||
`UserInDB(**user_dict)` 表示:
|
||||
`UserInDB(**user_dict)` 是指:
|
||||
|
||||
*直接将 `user_dict` 的键和值作为关键字参数传递,等同于:*
|
||||
*直接把 `user_dict` 的键与值当作关键字参数传递,等效于:*
|
||||
|
||||
```Python
|
||||
UserInDB(
|
||||
@@ -138,75 +142,79 @@ UserInDB(
|
||||
)
|
||||
```
|
||||
|
||||
!!! info
|
||||
有关 `user_dict` 的更完整说明,请参阅[**额外的模型**文档](../extra-models.md#about-user_indict){.internal-link target=_blank}。
|
||||
!!! info "说明"
|
||||
|
||||
## 返回令牌
|
||||
`user_dict` 的说明,详见[**更多模型**一章](../extra-models.md#about-user_indict){.internal-link target=_blank}。
|
||||
|
||||
`token` 端点的响应必须是一个 JSON 对象。
|
||||
## 返回 Token
|
||||
|
||||
它应该有一个 `token_type`。在我们的例子中,由于我们使用的是「Bearer」令牌,因此令牌类型应为「`bearer`」。
|
||||
`token` 端点的响应必须是 JSON 对象。
|
||||
|
||||
并且还应该有一个 `access_token` 字段,它是一个包含我们的访问令牌的字符串。
|
||||
响应返回的内容应该包含 `token_type`。本例中用的是**Bearer**Token,因此, Token 类型应为**`bearer`**。
|
||||
|
||||
对于这个简单的示例,我们将极其不安全地返回相同的 `username` 作为令牌。
|
||||
返回内容还应包含 `access_token` 字段,它是包含权限 Token 的字符串。
|
||||
|
||||
!!! tip
|
||||
在下一章中,你将看到一个真实的安全实现,使用了哈希密码和 <abbr title="JSON Web Tokens">JWT</abbr> 令牌。
|
||||
本例只是简单的演示,返回的 Token 就是 `username`,但这种方式极不安全。
|
||||
|
||||
但现在,让我们仅关注我们需要的特定细节。
|
||||
!!! tip "提示"
|
||||
|
||||
下一章介绍使用哈希密码和 <abbr title="JSON Web Tokens">JWT</abbr> Token 的真正安全机制。
|
||||
|
||||
但现在,仅关注所需的特定细节。
|
||||
|
||||
```Python hl_lines="85"
|
||||
{!../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
根据规范,你应该像本示例一样,返回一个带有 `access_token` 和 `token_type` 的 JSON。
|
||||
!!! tip "提示"
|
||||
|
||||
这是你必须在代码中自行完成的工作,并且要确保使用了这些 JSON 字段。
|
||||
按规范的要求,应像本示例一样,返回带有 `access_token` 和 `token_type` 的 JSON 对象。
|
||||
|
||||
这几乎是唯一的你需要自己记住并正确地执行以符合规范的事情。
|
||||
这是开发者必须在代码中自行完成的工作,并且要确保使用这些 JSON 的键。
|
||||
|
||||
其余的,**FastAPI** 都会为你处理。
|
||||
这几乎是唯一需要开发者牢记在心,并按规范要求正确执行的事。
|
||||
|
||||
**FastAPI** 则负责处理其它的工作。
|
||||
|
||||
## 更新依赖项
|
||||
|
||||
现在我们将更新我们的依赖项。
|
||||
接下来,更新依赖项。
|
||||
|
||||
我们想要仅当此用户处于启用状态时才能获取 `current_user`。
|
||||
使之仅在当前用户为激活状态时,才能获取 `current_user`。
|
||||
|
||||
因此,我们创建了一个额外的依赖项 `get_current_active_user`,而该依赖项又以 `get_current_user` 作为依赖项。
|
||||
为此,要再创建一个依赖项 `get_current_active_user`,此依赖项以 `get_current_user` 依赖项为基础。
|
||||
|
||||
如果用户不存在或处于未启用状态,则这两个依赖项都将仅返回 HTTP 错误。
|
||||
如果用户不存在,或状态为未激活,这两个依赖项都会返回 HTTP 错误。
|
||||
|
||||
因此,在我们的端点中,只有当用户存在,身份认证通过且处于启用状态时,我们才能获得该用户:
|
||||
因此,在端点中,只有当用户存在、通过身份验证、且状态为激活时,才能获得该用户:
|
||||
|
||||
```Python hl_lines="58-67 69-72 90"
|
||||
{!../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
我们在此处返回的值为 `Bearer` 的额外响应头 `WWW-Authenticate` 也是规范的一部分。
|
||||
!!! info "说明"
|
||||
|
||||
任何的 401「未认证」HTTP(错误)状态码都应该返回 `WWW-Authenticate` 响应头。
|
||||
此处返回值为 `Bearer` 的响应头 `WWW-Authenticate` 也是规范的一部分。
|
||||
|
||||
对于 bearer 令牌(我们的例子),该响应头的值应为 `Bearer`。
|
||||
任何 401**UNAUTHORIZED**HTTP(错误)状态码都应返回 `WWW-Authenticate` 响应头。
|
||||
|
||||
实际上你可以忽略这个额外的响应头,不会有什么问题。
|
||||
本例中,因为使用的是 Bearer Token,该响应头的值应为 `Bearer`。
|
||||
|
||||
但此处提供了它以符合规范。
|
||||
实际上,忽略这个附加响应头,也不会有什么问题。
|
||||
|
||||
而且,(现在或将来)可能会有工具期望得到并使用它,然后对你或你的用户有用处。
|
||||
之所以在此提供这个附加响应头,是为了符合规范的要求。
|
||||
|
||||
这就是遵循标准的好处...
|
||||
说不定什么时候,就有工具用得上它,而且,开发者或用户也可能用得上。
|
||||
|
||||
这就是遵循标准的好处……
|
||||
|
||||
## 实际效果
|
||||
|
||||
打开交互式文档:<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="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>。
|
||||
|
||||
### 身份认证
|
||||
### 身份验证
|
||||
|
||||
点击「Authorize」按钮。
|
||||
点击**Authorize**按钮。
|
||||
|
||||
使用以下凭证:
|
||||
|
||||
@@ -216,15 +224,15 @@ UserInDB(
|
||||
|
||||
<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` 操作。
|
||||
使用 `/users/me` 路径的 `GET` 操作。
|
||||
|
||||
你将获得你的用户数据,如:
|
||||
可以提取如下当前用户数据:
|
||||
|
||||
```JSON
|
||||
{
|
||||
@@ -238,7 +246,7 @@ UserInDB(
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/security/image06.png">
|
||||
|
||||
如果你点击锁定图标并注销,然后再次尝试同一操作,则会得到 HTTP 401 错误:
|
||||
点击小锁图标,注销后,再执行同样的操作,则会得到 HTTP 401 错误:
|
||||
|
||||
```JSON
|
||||
{
|
||||
@@ -246,17 +254,17 @@ UserInDB(
|
||||
}
|
||||
```
|
||||
|
||||
### 未启用的用户
|
||||
### 未激活用户
|
||||
|
||||
现在尝试使用未启用的用户,并通过以下方式进行身份认证:
|
||||
测试未激活用户,输入以下信息,进行身份验证:
|
||||
|
||||
用户名:`alice`
|
||||
|
||||
密码:`secret2`
|
||||
|
||||
然后尝试执行 `/users/me` 路径的 `GET` 操作。
|
||||
然后,执行 `/users/me` 路径的 `GET` 操作。
|
||||
|
||||
你将得到一个「未启用的用户」错误,如:
|
||||
显示下列**未激活用户**错误信息:
|
||||
|
||||
```JSON
|
||||
{
|
||||
@@ -264,12 +272,12 @@ UserInDB(
|
||||
}
|
||||
```
|
||||
|
||||
## 总结
|
||||
## 小结
|
||||
|
||||
现在你掌握了为你的 API 实现一个基于 `username` 和 `password` 的完整安全系统的工具。
|
||||
使用本章的工具实现基于 `username` 和 `password` 的完整 API 安全系统。
|
||||
|
||||
使用这些工具,你可以使安全系统与任何数据库以及任何用户或数据模型兼容。
|
||||
这些工具让安全系统兼容任何数据库、用户及数据模型。
|
||||
|
||||
唯一缺少的细节是它实际上还并不「安全」。
|
||||
唯一欠缺的是,它仍然不是真的**安全**。
|
||||
|
||||
在下一章中,你将看到如何使用一个安全的哈希密码库和 <abbr title="JSON Web Tokens">JWT</abbr> 令牌。
|
||||
下一章,介绍使用密码哈希支持库与 <abbr title="JSON Web Tokens">JWT</abbr> 令牌实现真正的安全机制。
|
||||
|
||||
@@ -6,7 +6,7 @@ from pydantic import BaseModel
|
||||
|
||||
class User(BaseModel):
|
||||
id: int
|
||||
name = "John Doe"
|
||||
name: str = "John Doe"
|
||||
signup_ts: Union[datetime, None] = None
|
||||
friends: List[int] = []
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ from pydantic import BaseModel
|
||||
|
||||
class User(BaseModel):
|
||||
id: int
|
||||
name = "John Doe"
|
||||
name: str = "John Doe"
|
||||
signup_ts: datetime | None = None
|
||||
friends: list[int] = []
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ from pydantic import BaseModel
|
||||
|
||||
class User(BaseModel):
|
||||
id: int
|
||||
name = "John Doe"
|
||||
name: str = "John Doe"
|
||||
signup_ts: Union[datetime, None] = None
|
||||
friends: list[int] = []
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
||||
|
||||
__version__ = "0.103.0"
|
||||
__version__ = "0.103.2"
|
||||
|
||||
from starlette import status as status
|
||||
|
||||
|
||||
@@ -58,9 +58,15 @@ if PYDANTIC_V2:
|
||||
from pydantic_core import CoreSchema as CoreSchema
|
||||
from pydantic_core import PydanticUndefined, PydanticUndefinedType
|
||||
from pydantic_core import Url as Url
|
||||
from pydantic_core.core_schema import (
|
||||
general_plain_validator_function as general_plain_validator_function,
|
||||
)
|
||||
|
||||
try:
|
||||
from pydantic_core.core_schema import (
|
||||
with_info_plain_validator_function as with_info_plain_validator_function,
|
||||
)
|
||||
except ImportError: # pragma: no cover
|
||||
from pydantic_core.core_schema import (
|
||||
general_plain_validator_function as with_info_plain_validator_function, # noqa: F401
|
||||
)
|
||||
|
||||
Required = PydanticUndefined
|
||||
Undefined = PydanticUndefined
|
||||
@@ -345,7 +351,7 @@ else:
|
||||
class PydanticSchemaGenerationError(Exception): # type: ignore[no-redef]
|
||||
pass
|
||||
|
||||
def general_plain_validator_function( # type: ignore[misc]
|
||||
def with_info_plain_validator_function( # type: ignore[misc]
|
||||
function: Callable[..., Any],
|
||||
*,
|
||||
ref: Union[str, None] = None,
|
||||
|
||||
@@ -189,20 +189,20 @@ class FastAPI(Starlette):
|
||||
# contextvars.
|
||||
# This needs to happen after user middlewares because those create a
|
||||
# new contextvars context copy by using a new AnyIO task group.
|
||||
# The initial part of dependencies with yield is executed in the
|
||||
# FastAPI code, inside all the middlewares, but the teardown part
|
||||
# (after yield) is executed in the AsyncExitStack in this middleware,
|
||||
# if the AsyncExitStack lived outside of the custom middlewares and
|
||||
# contextvars were set in a dependency with yield in that internal
|
||||
# The initial part of dependencies with 'yield' is executed in the
|
||||
# FastAPI code, inside all the middlewares. However, the teardown part
|
||||
# (after 'yield') is executed in the AsyncExitStack in this middleware.
|
||||
# If the AsyncExitStack lived outside of the custom middlewares and
|
||||
# contextvars were set in a dependency with 'yield' in that internal
|
||||
# contextvars context, the values would not be available in the
|
||||
# outside context of the AsyncExitStack.
|
||||
# By putting the middleware and the AsyncExitStack here, inside all
|
||||
# user middlewares, the code before and after yield in dependencies
|
||||
# with yield is executed in the same contextvars context, so all values
|
||||
# set in contextvars before yield is still available after yield as
|
||||
# would be expected.
|
||||
# outer context of the AsyncExitStack.
|
||||
# By placing the middleware and the AsyncExitStack here, inside all
|
||||
# user middlewares, the code before and after 'yield' in dependencies
|
||||
# with 'yield' is executed in the same contextvars context. Thus, all values
|
||||
# set in contextvars before 'yield' are still available after 'yield,' as
|
||||
# expected.
|
||||
# Additionally, by having this AsyncExitStack here, after the
|
||||
# ExceptionMiddleware, now dependencies can catch handled exceptions,
|
||||
# ExceptionMiddleware, dependencies can now catch handled exceptions,
|
||||
# e.g. HTTPException, to customize the teardown code (e.g. DB session
|
||||
# rollback).
|
||||
Middleware(AsyncExitStackMiddleware),
|
||||
|
||||
@@ -5,7 +5,7 @@ from fastapi._compat import (
|
||||
CoreSchema,
|
||||
GetJsonSchemaHandler,
|
||||
JsonSchemaValue,
|
||||
general_plain_validator_function,
|
||||
with_info_plain_validator_function,
|
||||
)
|
||||
from starlette.datastructures import URL as URL # noqa: F401
|
||||
from starlette.datastructures import Address as Address # noqa: F401
|
||||
@@ -49,7 +49,7 @@ class UploadFile(StarletteUploadFile):
|
||||
def __get_pydantic_core_schema__(
|
||||
cls, source: Type[Any], handler: Callable[[Any], CoreSchema]
|
||||
) -> CoreSchema:
|
||||
return general_plain_validator_function(cls._validate)
|
||||
return with_info_plain_validator_function(cls._validate)
|
||||
|
||||
|
||||
class DefaultPlaceholder:
|
||||
|
||||
@@ -7,7 +7,7 @@ from fastapi._compat import (
|
||||
GetJsonSchemaHandler,
|
||||
JsonSchemaValue,
|
||||
_model_rebuild,
|
||||
general_plain_validator_function,
|
||||
with_info_plain_validator_function,
|
||||
)
|
||||
from fastapi.logger import logger
|
||||
from pydantic import AnyUrl, BaseModel, Field
|
||||
@@ -52,7 +52,7 @@ except ImportError: # pragma: no cover
|
||||
def __get_pydantic_core_schema__(
|
||||
cls, source: Type[Any], handler: Callable[[Any], CoreSchema]
|
||||
) -> CoreSchema:
|
||||
return general_plain_validator_function(cls._validate)
|
||||
return with_info_plain_validator_function(cls._validate)
|
||||
|
||||
|
||||
class Contact(BaseModel):
|
||||
|
||||
@@ -44,6 +44,8 @@ dependencies = [
|
||||
"starlette>=0.27.0,<0.28.0",
|
||||
"pydantic>=1.7.4,!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0",
|
||||
"typing-extensions>=4.5.0",
|
||||
# TODO: remove this pin after upgrading Starlette 0.31.1
|
||||
"anyio>=3.7.1,<4.0.0",
|
||||
]
|
||||
dynamic = ["version"]
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ def test_model_field_default_required():
|
||||
|
||||
|
||||
@needs_pydanticv1
|
||||
def test_upload_file_dummy_general_plain_validator_function():
|
||||
def test_upload_file_dummy_with_info_plain_validator_function():
|
||||
# For coverage
|
||||
assert UploadFile.__get_pydantic_core_schema__(str, lambda x: None) == {}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ from .utils import needs_pydanticv2
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_client():
|
||||
from pydantic import BaseModel, FieldValidationInfo, field_validator
|
||||
from pydantic import BaseModel, ValidationInfo, field_validator
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@@ -28,7 +28,7 @@ def get_client():
|
||||
foo: ModelB
|
||||
|
||||
@field_validator("name")
|
||||
def lower_username(cls, name: str, info: FieldValidationInfo):
|
||||
def lower_username(cls, name: str, info: ValidationInfo):
|
||||
if not name.endswith("A"):
|
||||
raise ValueError("name must end in A")
|
||||
return name
|
||||
|
||||
@@ -125,6 +125,9 @@ client = TestClient(app)
|
||||
|
||||
|
||||
def test_call_api():
|
||||
response = client.post("/examples/", json={"data": "example1"})
|
||||
assert response.status_code == 200, response.text
|
||||
|
||||
response = client.get("/path_examples/foo")
|
||||
assert response.status_code == 200, response.text
|
||||
|
||||
|
||||
@@ -4,19 +4,23 @@ from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel
|
||||
|
||||
from .utils import needs_pydanticv2
|
||||
from .utils import PYDANTIC_V2, needs_pydanticv2
|
||||
|
||||
|
||||
class SubItem(BaseModel):
|
||||
subname: str
|
||||
sub_description: Optional[str] = None
|
||||
tags: List[str] = []
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"json_schema_serialization_defaults_required": True}
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
description: Optional[str] = None
|
||||
sub: Optional[SubItem] = None
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"json_schema_serialization_defaults_required": True}
|
||||
|
||||
|
||||
def get_app_client(separate_input_output_schemas: bool = True) -> TestClient:
|
||||
|
||||
@@ -52,9 +52,7 @@ def test_openapi_schema(client: TestClient):
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item-Output"
|
||||
}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -86,9 +84,7 @@ def test_openapi_schema(client: TestClient):
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item-Output"
|
||||
}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -116,7 +112,7 @@ def test_openapi_schema(client: TestClient):
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item-Input"}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
@@ -126,35 +122,9 @@ def test_openapi_schema(client: TestClient):
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Item-Input": {
|
||||
"title": "Item",
|
||||
"Item": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"price": {
|
||||
"title": "Price",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
"tax": {"title": "Tax", "type": "number", "default": 10.5},
|
||||
"tags": {
|
||||
"title": "Tags",
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"default": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
"Item-Output": {
|
||||
"title": "Item",
|
||||
"type": "object",
|
||||
"required": ["name", "description", "price", "tax", "tags"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
|
||||
@@ -55,9 +55,7 @@ def test_openapi_schema(client: TestClient):
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item-Output"
|
||||
}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -89,9 +87,7 @@ def test_openapi_schema(client: TestClient):
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item-Output"
|
||||
}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -119,7 +115,7 @@ def test_openapi_schema(client: TestClient):
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item-Input"}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
@@ -129,35 +125,9 @@ def test_openapi_schema(client: TestClient):
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Item-Input": {
|
||||
"title": "Item",
|
||||
"Item": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"price": {
|
||||
"title": "Price",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
"tax": {"title": "Tax", "type": "number", "default": 10.5},
|
||||
"tags": {
|
||||
"title": "Tags",
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"default": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
"Item-Output": {
|
||||
"title": "Item",
|
||||
"type": "object",
|
||||
"required": ["name", "description", "price", "tax", "tags"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
|
||||
@@ -55,9 +55,7 @@ def test_openapi_schema(client: TestClient):
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item-Output"
|
||||
}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -89,9 +87,7 @@ def test_openapi_schema(client: TestClient):
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item-Output"
|
||||
}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -119,7 +115,7 @@ def test_openapi_schema(client: TestClient):
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item-Input"}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
@@ -129,35 +125,9 @@ def test_openapi_schema(client: TestClient):
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Item-Input": {
|
||||
"title": "Item",
|
||||
"Item": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"title": "Name",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"price": {
|
||||
"title": "Price",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
"tax": {"title": "Tax", "type": "number", "default": 10.5},
|
||||
"tags": {
|
||||
"title": "Tags",
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"default": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
"Item-Output": {
|
||||
"title": "Item",
|
||||
"type": "object",
|
||||
"required": ["name", "description", "price", "tax", "tags"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
|
||||
@@ -79,9 +79,7 @@ def test_openapi_schema():
|
||||
"schema": {
|
||||
"title": "Items",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Item-Input"
|
||||
},
|
||||
"items": {"$ref": "#/components/schemas/Item"},
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -136,14 +134,14 @@ def test_openapi_schema():
|
||||
"schemas": {
|
||||
"Author": {
|
||||
"title": "Author",
|
||||
"required": ["name", "items"],
|
||||
"required": ["name"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"items": {
|
||||
"title": "Items",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/Item-Output"},
|
||||
"items": {"$ref": "#/components/schemas/Item"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -158,27 +156,15 @@ def test_openapi_schema():
|
||||
}
|
||||
},
|
||||
},
|
||||
"Item-Input": {
|
||||
"Item": {
|
||||
"title": "Item",
|
||||
"required": ["name"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
"Item-Output": {
|
||||
"title": "Item",
|
||||
"required": ["name", "description"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -34,9 +34,7 @@ def test_openapi_schema():
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item-Output"
|
||||
}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -57,7 +55,7 @@ def test_openapi_schema():
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item-Input"}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
@@ -67,7 +65,7 @@ def test_openapi_schema():
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Item-Input": {
|
||||
"Item": {
|
||||
"title": "Item",
|
||||
"required": ["name", "price"],
|
||||
"type": "object",
|
||||
@@ -91,30 +89,6 @@ def test_openapi_schema():
|
||||
},
|
||||
},
|
||||
},
|
||||
"Item-Output": {
|
||||
"title": "Item",
|
||||
"required": ["name", "description", "price", "tax", "tags"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"description": {
|
||||
"title": "Description",
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
},
|
||||
"price": {"title": "Price", "type": "number"},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
"tags": {
|
||||
"title": "Tags",
|
||||
"uniqueItems": True,
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"default": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
|
||||
@@ -34,9 +34,7 @@ def test_openapi_schema():
|
||||
"description": "The created item",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item-Output"
|
||||
}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -57,7 +55,7 @@ def test_openapi_schema():
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item-Input"}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
@@ -67,7 +65,7 @@ def test_openapi_schema():
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Item-Input": {
|
||||
"Item": {
|
||||
"title": "Item",
|
||||
"required": ["name", "price"],
|
||||
"type": "object",
|
||||
@@ -91,30 +89,6 @@ def test_openapi_schema():
|
||||
},
|
||||
},
|
||||
},
|
||||
"Item-Output": {
|
||||
"title": "Item",
|
||||
"required": ["name", "description", "price", "tax", "tags"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"description": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Description",
|
||||
},
|
||||
"price": {"title": "Price", "type": "number"},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
"tags": {
|
||||
"title": "Tags",
|
||||
"uniqueItems": True,
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"default": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
|
||||
@@ -41,9 +41,7 @@ def test_openapi_schema(client: TestClient):
|
||||
"description": "The created item",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item-Output"
|
||||
}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -64,7 +62,7 @@ def test_openapi_schema(client: TestClient):
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item-Input"}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
@@ -74,7 +72,7 @@ def test_openapi_schema(client: TestClient):
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Item-Input": {
|
||||
"Item": {
|
||||
"title": "Item",
|
||||
"required": ["name", "price"],
|
||||
"type": "object",
|
||||
@@ -98,30 +96,6 @@ def test_openapi_schema(client: TestClient):
|
||||
},
|
||||
},
|
||||
},
|
||||
"Item-Output": {
|
||||
"title": "Item",
|
||||
"required": ["name", "description", "price", "tax", "tags"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"description": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Description",
|
||||
},
|
||||
"price": {"title": "Price", "type": "number"},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
"tags": {
|
||||
"title": "Tags",
|
||||
"uniqueItems": True,
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"default": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
|
||||
@@ -41,9 +41,7 @@ def test_openapi_schema(client: TestClient):
|
||||
"description": "The created item",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item-Output"
|
||||
}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -64,7 +62,7 @@ def test_openapi_schema(client: TestClient):
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item-Input"}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
@@ -74,7 +72,7 @@ def test_openapi_schema(client: TestClient):
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Item-Input": {
|
||||
"Item": {
|
||||
"title": "Item",
|
||||
"required": ["name", "price"],
|
||||
"type": "object",
|
||||
@@ -98,30 +96,6 @@ def test_openapi_schema(client: TestClient):
|
||||
},
|
||||
},
|
||||
},
|
||||
"Item-Output": {
|
||||
"title": "Item",
|
||||
"required": ["name", "description", "price", "tax", "tags"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"title": "Name", "type": "string"},
|
||||
"description": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Description",
|
||||
},
|
||||
"price": {"title": "Price", "type": "number"},
|
||||
"tax": {
|
||||
"title": "Tax",
|
||||
"anyOf": [{"type": "number"}, {"type": "null"}],
|
||||
},
|
||||
"tags": {
|
||||
"title": "Tags",
|
||||
"uniqueItems": True,
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"default": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
|
||||
@@ -33,9 +33,9 @@ def test_get_enums_invalid():
|
||||
{
|
||||
"type": "enum",
|
||||
"loc": ["path", "model_name"],
|
||||
"msg": "Input should be 'alexnet','resnet' or 'lenet'",
|
||||
"msg": "Input should be 'alexnet', 'resnet' or 'lenet'",
|
||||
"input": "foo",
|
||||
"ctx": {"expected": "'alexnet','resnet' or 'lenet'"},
|
||||
"ctx": {"expected": "'alexnet', 'resnet' or 'lenet'"},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -48,9 +48,7 @@ def test_openapi_schema(client: TestClient) -> None:
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Item-Output"
|
||||
},
|
||||
"items": {"$ref": "#/components/schemas/Item"},
|
||||
"type": "array",
|
||||
"title": "Response Read Items Items Get",
|
||||
}
|
||||
@@ -65,7 +63,7 @@ def test_openapi_schema(client: TestClient) -> None:
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item-Input"}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
@@ -102,7 +100,7 @@ def test_openapi_schema(client: TestClient) -> None:
|
||||
"type": "object",
|
||||
"title": "HTTPValidationError",
|
||||
},
|
||||
"Item-Input": {
|
||||
"Item": {
|
||||
"properties": {
|
||||
"name": {"type": "string", "title": "Name"},
|
||||
"description": {
|
||||
@@ -114,18 +112,6 @@ def test_openapi_schema(client: TestClient) -> None:
|
||||
"required": ["name"],
|
||||
"title": "Item",
|
||||
},
|
||||
"Item-Output": {
|
||||
"properties": {
|
||||
"name": {"type": "string", "title": "Name"},
|
||||
"description": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Description",
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
"required": ["name", "description"],
|
||||
"title": "Item",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
|
||||
@@ -51,9 +51,7 @@ def test_openapi_schema(client: TestClient) -> None:
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Item-Output"
|
||||
},
|
||||
"items": {"$ref": "#/components/schemas/Item"},
|
||||
"type": "array",
|
||||
"title": "Response Read Items Items Get",
|
||||
}
|
||||
@@ -68,7 +66,7 @@ def test_openapi_schema(client: TestClient) -> None:
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item-Input"}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
@@ -105,7 +103,7 @@ def test_openapi_schema(client: TestClient) -> None:
|
||||
"type": "object",
|
||||
"title": "HTTPValidationError",
|
||||
},
|
||||
"Item-Input": {
|
||||
"Item": {
|
||||
"properties": {
|
||||
"name": {"type": "string", "title": "Name"},
|
||||
"description": {
|
||||
@@ -117,18 +115,6 @@ def test_openapi_schema(client: TestClient) -> None:
|
||||
"required": ["name"],
|
||||
"title": "Item",
|
||||
},
|
||||
"Item-Output": {
|
||||
"properties": {
|
||||
"name": {"type": "string", "title": "Name"},
|
||||
"description": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Description",
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
"required": ["name", "description"],
|
||||
"title": "Item",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
|
||||
@@ -51,9 +51,7 @@ def test_openapi_schema(client: TestClient) -> None:
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Item-Output"
|
||||
},
|
||||
"items": {"$ref": "#/components/schemas/Item"},
|
||||
"type": "array",
|
||||
"title": "Response Read Items Items Get",
|
||||
}
|
||||
@@ -68,7 +66,7 @@ def test_openapi_schema(client: TestClient) -> None:
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/Item-Input"}
|
||||
"schema": {"$ref": "#/components/schemas/Item"}
|
||||
}
|
||||
},
|
||||
"required": True,
|
||||
@@ -105,7 +103,7 @@ def test_openapi_schema(client: TestClient) -> None:
|
||||
"type": "object",
|
||||
"title": "HTTPValidationError",
|
||||
},
|
||||
"Item-Input": {
|
||||
"Item": {
|
||||
"properties": {
|
||||
"name": {"type": "string", "title": "Name"},
|
||||
"description": {
|
||||
@@ -117,18 +115,6 @@ def test_openapi_schema(client: TestClient) -> None:
|
||||
"required": ["name"],
|
||||
"title": "Item",
|
||||
},
|
||||
"Item-Output": {
|
||||
"properties": {
|
||||
"name": {"type": "string", "title": "Name"},
|
||||
"description": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"title": "Description",
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
"required": ["name", "description"],
|
||||
"title": "Item",
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
|
||||
Reference in New Issue
Block a user