mirror of
https://github.com/fastapi/fastapi.git
synced 2025-12-24 14:48:35 -05:00
Compare commits
248 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ccd242348f | ||
|
|
066cfae56e | ||
|
|
51e768e85a | ||
|
|
10fbfd6dc7 | ||
|
|
85e602d7cc | ||
|
|
fbc13d1f5b | ||
|
|
d4e2bdb33a | ||
|
|
8a5befd099 | ||
|
|
9a442c9730 | ||
|
|
4fa4965beb | ||
|
|
5f4680201c | ||
|
|
5cd99a9517 | ||
|
|
b6ea8414a9 | ||
|
|
be3e29fb3c | ||
|
|
cf730518bc | ||
|
|
d62f5c1b28 | ||
|
|
4cf9075809 | ||
|
|
a0c677ef0d | ||
|
|
54aa27ca07 | ||
|
|
ac9f56ea5e | ||
|
|
ed9425ef50 | ||
|
|
9a85535e7f | ||
|
|
c9308cf070 | ||
|
|
058cb6e88e | ||
|
|
876ea7978f | ||
|
|
da0bfd22aa | ||
|
|
d0917ce015 | ||
|
|
6002290659 | ||
|
|
e92a8649f9 | ||
|
|
c28337e61d | ||
|
|
f4aea58528 | ||
|
|
fcab59be88 | ||
|
|
6aa9ef0c96 | ||
|
|
c7fe6fea33 | ||
|
|
c53e5bd4b1 | ||
|
|
db4452d47e | ||
|
|
53127efde5 | ||
|
|
9974c4b6ac | ||
|
|
7ff62468a0 | ||
|
|
38493f8ae1 | ||
|
|
e0945eb1c8 | ||
|
|
a26a3c1cbf | ||
|
|
2889b4a3df | ||
|
|
8b20eece4c | ||
|
|
330e8112ac | ||
|
|
7a2e9c7aaa | ||
|
|
1613749cc3 | ||
|
|
669b3a4cb8 | ||
|
|
5f089435e5 | ||
|
|
f1c61dec0c | ||
|
|
a96effa86e | ||
|
|
29c36f9d3f | ||
|
|
fcf49a04eb | ||
|
|
558d929568 | ||
|
|
f3086a7b15 | ||
|
|
64d512e349 | ||
|
|
88556dafb6 | ||
|
|
6a46532cc4 | ||
|
|
c75de8cba2 | ||
|
|
85443e64ee | ||
|
|
2623a06105 | ||
|
|
d72599b4dc | ||
|
|
16e058697d | ||
|
|
bbfa450991 | ||
|
|
22524a1610 | ||
|
|
959f6bf209 | ||
|
|
80eac96c70 | ||
|
|
bbb8fe1e60 | ||
|
|
bfb1422555 | ||
|
|
0cc40ed664 | ||
|
|
4a1c69e6c2 | ||
|
|
42a4ed7a18 | ||
|
|
146b9d6e04 | ||
|
|
e0d1619362 | ||
|
|
fdfcb9412e | ||
|
|
866a24f879 | ||
|
|
ee4b2bb8ae | ||
|
|
f67b19f0f7 | ||
|
|
9dc1a3026d | ||
|
|
e13df8ee79 | ||
|
|
e04878edfe | ||
|
|
0e3ff851c2 | ||
|
|
e866a2c7e1 | ||
|
|
90fc4299d1 | ||
|
|
a3a37a4213 | ||
|
|
3c6528460c | ||
|
|
5ba0c8c002 | ||
|
|
0ae8db447a | ||
|
|
9c6086eee6 | ||
|
|
ebe69913ae | ||
|
|
81115dba53 | ||
|
|
1d1859675f | ||
|
|
c6aa28bea2 | ||
|
|
20f689ded2 | ||
|
|
1213227667 | ||
|
|
e782ba43ce | ||
|
|
6ddd0c64b0 | ||
|
|
a05e8b4e6f | ||
|
|
e83aa43296 | ||
|
|
95cbb43b06 | ||
|
|
babe2f9b03 | ||
|
|
add7c4800c | ||
|
|
b741ea7619 | ||
|
|
74ce2204ae | ||
|
|
823df88c34 | ||
|
|
3658733b5e | ||
|
|
715c0341a9 | ||
|
|
adcf03f2bc | ||
|
|
1073062c7f | ||
|
|
7291cead65 | ||
|
|
4267bd1f4f | ||
|
|
b2aa3593be | ||
|
|
ed0fcba7cb | ||
|
|
22a155efc1 | ||
|
|
306326a213 | ||
|
|
4fec12b354 | ||
|
|
275306c369 | ||
|
|
4d270463af | ||
|
|
6620273083 | ||
|
|
0b4fe10c8f | ||
|
|
c4007cb9ec | ||
|
|
3ec498af63 | ||
|
|
895789bed0 | ||
|
|
ef5d6181b6 | ||
|
|
3079ba925e | ||
|
|
ddf6daeb07 | ||
|
|
f3efaf69da | ||
|
|
f8460a8b54 | ||
|
|
d0cc996dc7 | ||
|
|
c70fab38e7 | ||
|
|
80d68a6eda | ||
|
|
dacb689290 | ||
|
|
dd2f759bac | ||
|
|
4cff206ebb | ||
|
|
0195bb5706 | ||
|
|
0ae8d09189 | ||
|
|
9df22ab864 | ||
|
|
81967f8f93 | ||
|
|
7dd4a4f435 | ||
|
|
94b7527dfd | ||
|
|
a3a8d68715 | ||
|
|
ee035dfa9a | ||
|
|
5a79564dab | ||
|
|
dc1534736d | ||
|
|
fc559b5fcd | ||
|
|
0d43b6552b | ||
|
|
89839eb834 | ||
|
|
f266dc17d7 | ||
|
|
697ec94a7e | ||
|
|
ae369d879a | ||
|
|
198b7ef2cb | ||
|
|
68e04f6531 | ||
|
|
c00e1ec6bf | ||
|
|
d3ff7c620a | ||
|
|
fae28a9bd7 | ||
|
|
0e7478d39c | ||
|
|
dbb43da9c0 | ||
|
|
56f887de15 | ||
|
|
fbe1a803fc | ||
|
|
52b5b08910 | ||
|
|
e7e6404faf | ||
|
|
30b3905ef3 | ||
|
|
b1d0f1e970 | ||
|
|
7250c194da | ||
|
|
173b891603 | ||
|
|
6ae8f07d24 | ||
|
|
b83709add4 | ||
|
|
a71077c530 | ||
|
|
278adc012a | ||
|
|
356a57daa8 | ||
|
|
b9d7f86743 | ||
|
|
adf4e77dd6 | ||
|
|
0e1a9d1c0f | ||
|
|
d8b6aa630c | ||
|
|
0bb8920ae1 | ||
|
|
95c182a42c | ||
|
|
165d57db24 | ||
|
|
ae5280e501 | ||
|
|
d4b2ef8137 | ||
|
|
fd2080aece | ||
|
|
3c8d8c38a7 | ||
|
|
fa92dbf557 | ||
|
|
cd8854c4c7 | ||
|
|
b63398f4b5 | ||
|
|
728b961d35 | ||
|
|
5e34cb1868 | ||
|
|
bbd34c55d5 | ||
|
|
8a72d363c8 | ||
|
|
ee93ad952c | ||
|
|
d26674616c | ||
|
|
40a19fe261 | ||
|
|
8b4546352f | ||
|
|
b3f2f08251 | ||
|
|
3d3a7dbe7e | ||
|
|
d69b5f39b4 | ||
|
|
70213467a6 | ||
|
|
8d1d1703f4 | ||
|
|
1285ba4b2e | ||
|
|
6bbfd27c19 | ||
|
|
4c0b9b831c | ||
|
|
9e6dcba766 | ||
|
|
e1825589ba | ||
|
|
acc59df815 | ||
|
|
d86b54e79b | ||
|
|
6b77179e3b | ||
|
|
8dab25df71 | ||
|
|
22bed0008c | ||
|
|
de6ccd7754 | ||
|
|
26c68c6e0d | ||
|
|
dc10b81d05 | ||
|
|
1f2070af20 | ||
|
|
a95212565a | ||
|
|
d80b065b5e | ||
|
|
dde140d8e3 | ||
|
|
96c3f44a0e | ||
|
|
0539dd9cd3 | ||
|
|
aaf5a380df | ||
|
|
e3c055ba8f | ||
|
|
afe44f0b25 | ||
|
|
8cd8aa4b67 | ||
|
|
26097421d3 | ||
|
|
3df68694c0 | ||
|
|
f3e9dcd891 | ||
|
|
00bdf533ef | ||
|
|
ae56590c51 | ||
|
|
923e0ac0c1 | ||
|
|
a64387c3fc | ||
|
|
c8124496fc | ||
|
|
75792eb82b | ||
|
|
bb53d0b0ea | ||
|
|
f928f3390c | ||
|
|
d5c84594cb | ||
|
|
0968329ed7 | ||
|
|
880c8b37cf | ||
|
|
92181ef182 | ||
|
|
ca2fae0588 | ||
|
|
af3a6ef78b | ||
|
|
eb3ab337ab | ||
|
|
5215b39d50 | ||
|
|
9359a8d65f | ||
|
|
afaa0391a5 | ||
|
|
438656395a | ||
|
|
39319a7ede | ||
|
|
8c6ad35615 | ||
|
|
f90465f5b4 | ||
|
|
1835b3f76d | ||
|
|
2201f29be3 | ||
|
|
68f25120c5 |
@@ -17,3 +17,4 @@ nl: 4701
|
||||
uz: 4883
|
||||
sv: 5146
|
||||
he: 5157
|
||||
ta: 5434
|
||||
|
||||
6
.github/actions/people/app/main.py
vendored
6
.github/actions/people/app/main.py
vendored
@@ -260,6 +260,7 @@ class Settings(BaseSettings):
|
||||
input_token: SecretStr
|
||||
input_standard_token: SecretStr
|
||||
github_repository: str
|
||||
httpx_timeout: int = 30
|
||||
|
||||
|
||||
def get_graphql_response(
|
||||
@@ -270,9 +271,10 @@ def get_graphql_response(
|
||||
response = httpx.post(
|
||||
github_graphql_url,
|
||||
headers=headers,
|
||||
timeout=settings.httpx_timeout,
|
||||
json={"query": query, "variables": variables, "operationName": "Q"},
|
||||
)
|
||||
if not response.status_code == 200:
|
||||
if response.status_code != 200:
|
||||
logging.error(f"Response was not 200, after: {after}")
|
||||
logging.error(response.text)
|
||||
raise RuntimeError(response.text)
|
||||
@@ -431,7 +433,7 @@ if __name__ == "__main__":
|
||||
)
|
||||
authors = {**issue_authors, **pr_authors}
|
||||
maintainers_logins = {"tiangolo"}
|
||||
bot_names = {"codecov", "github-actions"}
|
||||
bot_names = {"codecov", "github-actions", "pre-commit-ci", "dependabot"}
|
||||
maintainers = []
|
||||
for login in maintainers_logins:
|
||||
user = authors[login]
|
||||
|
||||
9
.github/workflows/build-docs.yml
vendored
9
.github/workflows/build-docs.yml
vendored
@@ -23,17 +23,14 @@ jobs:
|
||||
with:
|
||||
path: ${{ env.pythonLocation }}
|
||||
key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-v03
|
||||
- name: Install Flit
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: python3.7 -m pip install flit
|
||||
- name: Install docs extras
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: python3.7 -m flit install --deps production --extras doc
|
||||
run: pip install .[doc]
|
||||
- name: Install Material for MkDocs Insiders
|
||||
if: ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false ) && steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install git+https://${{ secrets.ACTIONS_TOKEN }}@github.com/squidfunk/mkdocs-material-insiders.git
|
||||
- name: Build Docs
|
||||
run: python3.7 ./scripts/docs.py build-all
|
||||
run: python ./scripts/docs.py build-all
|
||||
- name: Zip docs
|
||||
run: bash ./scripts/zip-docs.sh
|
||||
- uses: actions/upload-artifact@v3
|
||||
@@ -41,7 +38,7 @@ jobs:
|
||||
name: docs-zip
|
||||
path: ./docs.zip
|
||||
- name: Deploy to Netlify
|
||||
uses: nwtgck/actions-netlify@v1.2.3
|
||||
uses: nwtgck/actions-netlify@v1.2.4
|
||||
with:
|
||||
publish-dir: './site'
|
||||
production-branch: master
|
||||
|
||||
4
.github/workflows/preview-docs.yml
vendored
4
.github/workflows/preview-docs.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Download Artifact Docs
|
||||
uses: dawidd6/action-download-artifact@v2.21.1
|
||||
uses: dawidd6/action-download-artifact@v2.24.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
workflow: build-docs.yml
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
rm -f docs.zip
|
||||
- name: Deploy to Netlify
|
||||
id: netlify
|
||||
uses: nwtgck/actions-netlify@v1.2.3
|
||||
uses: nwtgck/actions-netlify@v1.2.4
|
||||
with:
|
||||
publish-dir: './site'
|
||||
production-deploy: false
|
||||
|
||||
18
.github/workflows/publish.yml
vendored
18
.github/workflows/publish.yml
vendored
@@ -17,23 +17,21 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.6"
|
||||
python-version: "3.7"
|
||||
- uses: actions/cache@v3
|
||||
id: cache
|
||||
with:
|
||||
path: ${{ env.pythonLocation }}
|
||||
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-publish
|
||||
- name: Install Flit
|
||||
- name: Install build dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install flit
|
||||
- name: Install Dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: flit install --symlink
|
||||
run: pip install build
|
||||
- name: Build distribution
|
||||
run: python -m build
|
||||
- name: Publish
|
||||
env:
|
||||
FLIT_USERNAME: ${{ secrets.FLIT_USERNAME }}
|
||||
FLIT_PASSWORD: ${{ secrets.FLIT_PASSWORD }}
|
||||
run: bash scripts/publish.sh
|
||||
uses: pypa/gh-action-pypi-publish@v1.5.1
|
||||
with:
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
|
||||
35
.github/workflows/smokeshow.yml
vendored
Normal file
35
.github/workflows/smokeshow.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
name: Smokeshow
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [Test]
|
||||
types: [completed]
|
||||
|
||||
permissions:
|
||||
statuses: write
|
||||
|
||||
jobs:
|
||||
smokeshow:
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.9'
|
||||
|
||||
- run: pip install smokeshow
|
||||
|
||||
- uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: test.yml
|
||||
commit: ${{ github.event.workflow_run.head_sha }}
|
||||
|
||||
- run: smokeshow upload coverage-html
|
||||
env:
|
||||
SMOKESHOW_GITHUB_STATUS_DESCRIPTION: Coverage {coverage-percentage}
|
||||
SMOKESHOW_GITHUB_COVERAGE_THRESHOLD: 100
|
||||
SMOKESHOW_GITHUB_CONTEXT: coverage
|
||||
SMOKESHOW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SMOKESHOW_GITHUB_PR_HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
|
||||
SMOKESHOW_AUTH_KEY: ${{ secrets.SMOKESHOW_AUTH_KEY }}
|
||||
48
.github/workflows/test.yml
vendored
48
.github/workflows/test.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
|
||||
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
@@ -26,16 +26,48 @@ jobs:
|
||||
with:
|
||||
path: ${{ env.pythonLocation }}
|
||||
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test-v02
|
||||
- name: Install Flit
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install flit
|
||||
- name: Install Dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: flit install --symlink
|
||||
run: pip install -e .[all,dev,doc,test]
|
||||
- name: Lint
|
||||
if: ${{ matrix.python-version != '3.6' }}
|
||||
run: bash scripts/lint.sh
|
||||
- run: mkdir coverage
|
||||
- name: Test
|
||||
run: bash scripts/test.sh
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
env:
|
||||
COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}
|
||||
CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}
|
||||
- name: Store coverage files
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverage
|
||||
path: coverage
|
||||
coverage-combine:
|
||||
needs: [test]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.8'
|
||||
|
||||
- name: Get coverage files
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: coverage
|
||||
path: coverage
|
||||
|
||||
- run: pip install coverage[toml]
|
||||
|
||||
- run: ls -la coverage
|
||||
- run: coverage combine coverage
|
||||
- run: coverage report
|
||||
- run: coverage html --show-contexts --title "Coverage for ${{ github.sha }}"
|
||||
|
||||
- name: Store coverage HTML
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverage-html
|
||||
path: htmlcov
|
||||
|
||||
@@ -12,14 +12,14 @@ repos:
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v2.37.1
|
||||
rev: v3.1.0
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args:
|
||||
- --py3-plus
|
||||
- --keep-runtime-typing
|
||||
- repo: https://github.com/myint/autoflake
|
||||
rev: v1.4
|
||||
- repo: https://github.com/PyCQA/autoflake
|
||||
rev: v1.7.7
|
||||
hooks:
|
||||
- id: autoflake
|
||||
args:
|
||||
@@ -43,7 +43,7 @@ repos:
|
||||
name: isort (pyi)
|
||||
types: [pyi]
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 22.6.0
|
||||
rev: 22.10.0
|
||||
hooks:
|
||||
- id: black
|
||||
ci:
|
||||
|
||||
14
README.md
14
README.md
@@ -8,8 +8,8 @@
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg?event=push&branch=master" alt="Test">
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage">
|
||||
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://coverage-badge.samuelcolvin.workers.dev/tiangolo/fastapi.svg" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
@@ -27,12 +27,11 @@
|
||||
|
||||
---
|
||||
|
||||
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
|
||||
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.7+ based on standard Python type hints.
|
||||
|
||||
The key features are:
|
||||
|
||||
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance).
|
||||
|
||||
* **Fast to code**: Increase the speed to develop features by about 200% to 300%. *
|
||||
* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. *
|
||||
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
|
||||
@@ -50,7 +49,6 @@ The key features are:
|
||||
<a href="https://bit.ly/3dmXC5S" target="_blank" title="The data structure for unstructured multimodal data"><img src="https://fastapi.tiangolo.com/img/sponsors/docarray.svg"></a>
|
||||
<a href="https://bit.ly/3JJ7y5C" target="_blank" title="Build cross-modal and multimodal applications on the cloud"><img src="https://fastapi.tiangolo.com/img/sponsors/jina2.svg"></a>
|
||||
<a href="https://cryptapi.io/" target="_blank" title="CryptAPI: Your easy to use, secure and privacy oriented payment gateway."><img src="https://fastapi.tiangolo.com/img/sponsors/cryptapi.svg"></a>
|
||||
<a href="https://app.imgwhale.xyz/" target="_blank" title="The ultimate solution to unlimited and forever cloud storage."><img src="https://fastapi.tiangolo.com/img/sponsors/imgwhale.svg"></a>
|
||||
<a href="https://doist.com/careers/9B437B1615-wa-senior-backend-engineer-python" target="_blank" title="Help us migrate doist to FastAPI"><img src="https://fastapi.tiangolo.com/img/sponsors/doist.svg"></a>
|
||||
<a href="https://www.deta.sh/?ref=fastapi" target="_blank" title="The launchpad for all your (team's) ideas"><img src="https://fastapi.tiangolo.com/img/sponsors/deta.svg"></a>
|
||||
<a href="https://www.investsuite.com/jobs" target="_blank" title="Wealthtech jobs with FastAPI"><img src="https://fastapi.tiangolo.com/img/sponsors/investsuite.svg"></a>
|
||||
@@ -114,7 +112,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
|
||||
|
||||
## Requirements
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI stands on the shoulders of giants:
|
||||
|
||||
@@ -133,7 +131,7 @@ $ pip install fastapi
|
||||
|
||||
</div>
|
||||
|
||||
You will also need an ASGI server, for production such as <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
You will also need an ASGI server, for production such as <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
@@ -330,7 +328,7 @@ You do that with standard modern Python types.
|
||||
|
||||
You don't have to learn a new syntax, the methods or classes of a specific library, etc.
|
||||
|
||||
Just standard **Python 3.6+**.
|
||||
Just standard **Python 3.7+**.
|
||||
|
||||
For example, for an `int`:
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Learn more about it below. 👇
|
||||
|
||||
## Versions
|
||||
|
||||
The latest versions of FastAPI are supported.
|
||||
The latest version of FastAPI is supported.
|
||||
|
||||
You are encouraged to [write tests](https://fastapi.tiangolo.com/tutorial/testing/) for your application and update your FastAPI version frequently after ensuring that your tests are passing. This way you will benefit from the latest features, bug fixes, and **security fixes**.
|
||||
|
||||
|
||||
466
docs/az/docs/index.md
Normal file
466
docs/az/docs/index.md
Normal file
@@ -0,0 +1,466 @@
|
||||
|
||||
{!../../../docs/missing-translation.md!}
|
||||
|
||||
|
||||
<p align="center">
|
||||
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<em>FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg" alt="Test">
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
**Documentation**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
|
||||
|
||||
**Source Code**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
|
||||
|
||||
---
|
||||
|
||||
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
|
||||
|
||||
The key features are:
|
||||
|
||||
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance).
|
||||
|
||||
* **Fast to code**: Increase the speed to develop features by about 200% to 300%. *
|
||||
* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. *
|
||||
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
|
||||
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
|
||||
* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
|
||||
* **Robust**: Get production-ready code. With automatic interactive documentation.
|
||||
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
|
||||
<small>* estimation based on tests on an internal development team, building production applications.</small>
|
||||
|
||||
## Sponsors
|
||||
|
||||
<!-- sponsors -->
|
||||
|
||||
{% if sponsors %}
|
||||
{% for sponsor in sponsors.gold -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor -%}
|
||||
{%- for sponsor in sponsors.silver -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<!-- /sponsors -->
|
||||
|
||||
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a>
|
||||
|
||||
## Opinions
|
||||
|
||||
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_I’m over the moon excited about **FastAPI**. It’s so fun!_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
|
||||
|
||||
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**, the FastAPI of CLIs
|
||||
|
||||
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
||||
|
||||
If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be used in the terminal instead of a web API, check out <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
|
||||
|
||||
**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀
|
||||
|
||||
## Requirements
|
||||
|
||||
Python 3.7+
|
||||
|
||||
FastAPI stands on the shoulders of giants:
|
||||
|
||||
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> for the web parts.
|
||||
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> for the data parts.
|
||||
|
||||
## Installation
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install fastapi
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
You will also need an ASGI server, for production such as <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install "uvicorn[standard]"
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## Example
|
||||
|
||||
### Create it
|
||||
|
||||
* Create a file `main.py` with:
|
||||
|
||||
```Python
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
<details markdown="1">
|
||||
<summary>Or use <code>async def</code>...</summary>
|
||||
|
||||
If your code uses `async` / `await`, use `async def`:
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
async def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
**Note**:
|
||||
|
||||
If you don't know, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
|
||||
|
||||
</details>
|
||||
|
||||
### Run it
|
||||
|
||||
Run the server with:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
|
||||
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
INFO: Started reloader process [28720]
|
||||
INFO: Started server process [28722]
|
||||
INFO: Waiting for application startup.
|
||||
INFO: Application startup complete.
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<details markdown="1">
|
||||
<summary>About the command <code>uvicorn main:app --reload</code>...</summary>
|
||||
|
||||
The command `uvicorn main:app` refers to:
|
||||
|
||||
* `main`: the file `main.py` (the Python "module").
|
||||
* `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
|
||||
* `--reload`: make the server restart after code changes. Only do this for development.
|
||||
|
||||
</details>
|
||||
|
||||
### Check it
|
||||
|
||||
Open your browser at <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
|
||||
|
||||
You will see the JSON response as:
|
||||
|
||||
```JSON
|
||||
{"item_id": 5, "q": "somequery"}
|
||||
```
|
||||
|
||||
You already created an API that:
|
||||
|
||||
* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`.
|
||||
* Both _paths_ take `GET` <em>operations</em> (also known as HTTP _methods_).
|
||||
* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`.
|
||||
* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`.
|
||||
|
||||
### Interactive API docs
|
||||
|
||||
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
You will see the automatic interactive API documentation (provided by <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
|
||||
|
||||

|
||||
|
||||
### Alternative API docs
|
||||
|
||||
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
You will see the alternative automatic documentation (provided by <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
|
||||

|
||||
|
||||
## Example upgrade
|
||||
|
||||
Now modify the file `main.py` to receive a body from a `PUT` request.
|
||||
|
||||
Declare the body using standard Python types, thanks to Pydantic.
|
||||
|
||||
```Python hl_lines="4 9-12 25-27"
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
is_offer: Optional[bool] = None
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
|
||||
|
||||
@app.put("/items/{item_id}")
|
||||
def update_item(item_id: int, item: Item):
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
The server should reload automatically (because you added `--reload` to the `uvicorn` command above).
|
||||
|
||||
### Interactive API docs upgrade
|
||||
|
||||
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
* The interactive API documentation will be automatically updated, including the new body:
|
||||
|
||||

|
||||
|
||||
* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API:
|
||||
|
||||

|
||||
|
||||
* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen:
|
||||
|
||||

|
||||
|
||||
### Alternative API docs upgrade
|
||||
|
||||
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
* The alternative documentation will also reflect the new query parameter and body:
|
||||
|
||||

|
||||
|
||||
### Recap
|
||||
|
||||
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
|
||||
|
||||
You do that with standard modern Python types.
|
||||
|
||||
You don't have to learn a new syntax, the methods or classes of a specific library, etc.
|
||||
|
||||
Just standard **Python 3.6+**.
|
||||
|
||||
For example, for an `int`:
|
||||
|
||||
```Python
|
||||
item_id: int
|
||||
```
|
||||
|
||||
or for a more complex `Item` model:
|
||||
|
||||
```Python
|
||||
item: Item
|
||||
```
|
||||
|
||||
...and with that single declaration you get:
|
||||
|
||||
* Editor support, including:
|
||||
* Completion.
|
||||
* Type checks.
|
||||
* Validation of data:
|
||||
* Automatic and clear errors when the data is invalid.
|
||||
* Validation even for deeply nested JSON objects.
|
||||
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network to Python data and types. Reading from:
|
||||
* JSON.
|
||||
* Path parameters.
|
||||
* Query parameters.
|
||||
* Cookies.
|
||||
* Headers.
|
||||
* Forms.
|
||||
* Files.
|
||||
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of output data: converting from Python data and types to network data (as JSON):
|
||||
* Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc).
|
||||
* `datetime` objects.
|
||||
* `UUID` objects.
|
||||
* Database models.
|
||||
* ...and many more.
|
||||
* Automatic interactive API documentation, including 2 alternative user interfaces:
|
||||
* Swagger UI.
|
||||
* ReDoc.
|
||||
|
||||
---
|
||||
|
||||
Coming back to the previous code example, **FastAPI** will:
|
||||
|
||||
* Validate that there is an `item_id` in the path for `GET` and `PUT` requests.
|
||||
* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests.
|
||||
* If it is not, the client will see a useful, clear error.
|
||||
* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests.
|
||||
* As the `q` parameter is declared with `= None`, it is optional.
|
||||
* Without the `None` it would be required (as is the body in the case with `PUT`).
|
||||
* For `PUT` requests to `/items/{item_id}`, Read the body as JSON:
|
||||
* Check that it has a required attribute `name` that should be a `str`.
|
||||
* Check that it has a required attribute `price` that has to be a `float`.
|
||||
* Check that it has an optional attribute `is_offer`, that should be a `bool`, if present.
|
||||
* All this would also work for deeply nested JSON objects.
|
||||
* Convert from and to JSON automatically.
|
||||
* Document everything with OpenAPI, that can be used by:
|
||||
* Interactive documentation systems.
|
||||
* Automatic client code generation systems, for many languages.
|
||||
* Provide 2 interactive documentation web interfaces directly.
|
||||
|
||||
---
|
||||
|
||||
We just scratched the surface, but you already get the idea of how it all works.
|
||||
|
||||
Try changing the line with:
|
||||
|
||||
```Python
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
...from:
|
||||
|
||||
```Python
|
||||
... "item_name": item.name ...
|
||||
```
|
||||
|
||||
...to:
|
||||
|
||||
```Python
|
||||
... "item_price": item.price ...
|
||||
```
|
||||
|
||||
...and see how your editor will auto-complete the attributes and know their types:
|
||||
|
||||

|
||||
|
||||
For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
|
||||
|
||||
**Spoiler alert**: the tutorial - user guide includes:
|
||||
|
||||
* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**.
|
||||
* How to set **validation constraints** as `maximum_length` or `regex`.
|
||||
* A very powerful and easy to use **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
|
||||
* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth.
|
||||
* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic).
|
||||
* Many extra features (thanks to Starlette) as:
|
||||
* **WebSockets**
|
||||
* **GraphQL**
|
||||
* extremely easy tests based on `requests` and `pytest`
|
||||
* **CORS**
|
||||
* **Cookie Sessions**
|
||||
* ...and more.
|
||||
|
||||
## Performance
|
||||
|
||||
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
|
||||
|
||||
To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
|
||||
|
||||
## Optional Dependencies
|
||||
|
||||
Used by Pydantic:
|
||||
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - for faster JSON <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>.
|
||||
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - for email validation.
|
||||
|
||||
Used by Starlette:
|
||||
|
||||
* <a href="https://requests.readthedocs.io" target="_blank"><code>requests</code></a> - Required if you want to use the `TestClient`.
|
||||
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Required if you want to use the default template configuration.
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Required if you want to support form <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>, with `request.form()`.
|
||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Required for `SessionMiddleware` support.
|
||||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI).
|
||||
* <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - Required for `GraphQLApp` support.
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
|
||||
|
||||
Used by FastAPI / Starlette:
|
||||
|
||||
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application.
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
|
||||
|
||||
You can install all of these with `pip install fastapi[all]`.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the terms of the MIT license.
|
||||
@@ -111,7 +111,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
|
||||
|
||||
## Requirements
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI stands on the shoulders of giants:
|
||||
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
articles:
|
||||
english:
|
||||
- author: WayScript
|
||||
author_link: https://www.wayscript.com
|
||||
link: https://blog.wayscript.com/fast-api-quickstart/
|
||||
title: Quickstart Guide to Build and Host Responsive APIs with Fast API and WayScript
|
||||
- author: New Relic
|
||||
author_link: https://newrelic.com
|
||||
link: https://newrelic.com/instant-observability/fastapi/e559ec64-f765-4470-a15f-1901fcebb468
|
||||
title: How to monitor FastAPI application performance using Python agent
|
||||
- author: Jean-Baptiste Rocher
|
||||
author_link: https://hashnode.com/@jibrocher
|
||||
link: https://dev.indooroutdoor.io/series/fastapi-react-poll-app
|
||||
@@ -212,6 +220,10 @@ articles:
|
||||
author_link: https://twitter.com/MantoshMukul
|
||||
link: https://www.jetbrains.com/pycharm/guide/tutorials/fastapi-aws-kubernetes/
|
||||
title: Developing FastAPI Application using K8s & AWS
|
||||
- author: KrishNa
|
||||
author_link: https://medium.com/@krishnardt365
|
||||
link: https://medium.com/@krishnardt365/fastapi-docker-and-postgres-91943e71be92
|
||||
title: Fastapi, Docker(Docker compose) and Postgres
|
||||
german:
|
||||
- author: Nico Axtmann
|
||||
author_link: https://twitter.com/_nicoax
|
||||
|
||||
@@ -1,34 +1,25 @@
|
||||
sponsors:
|
||||
- - login: github
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9919?v=4
|
||||
url: https://github.com/github
|
||||
- - login: jina-ai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/60539444?v=4
|
||||
url: https://github.com/jina-ai
|
||||
- - login: Doist
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2565372?v=4
|
||||
url: https://github.com/Doist
|
||||
- login: cryptapi
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4
|
||||
url: https://github.com/cryptapi
|
||||
- login: BLUE-DEVIL1134
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/55914808?u=f283d674fce31be7fb3ed2665b0f20d89958e541&v=4
|
||||
url: https://github.com/BLUE-DEVIL1134
|
||||
- login: jina-ai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/60539444?v=4
|
||||
url: https://github.com/jina-ai
|
||||
- login: DropbaseHQ
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/85367855?v=4
|
||||
url: https://github.com/DropbaseHQ
|
||||
- - login: ObliviousAI
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/65656077?v=4
|
||||
url: https://github.com/ObliviousAI
|
||||
- login: Lovage-Labs
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/71685552?v=4
|
||||
url: https://github.com/Lovage-Labs
|
||||
- login: chaserowbotham
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/97751084?v=4
|
||||
url: https://github.com/chaserowbotham
|
||||
- - login: mikeckennedy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2035561?u=1bb18268bcd4d9249e1f783a063c27df9a84c05b&v=4
|
||||
url: https://github.com/mikeckennedy
|
||||
- login: Trivie
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4
|
||||
url: https://github.com/Trivie
|
||||
- login: deta
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/47275976?v=4
|
||||
url: https://github.com/deta
|
||||
@@ -41,15 +32,18 @@ sponsors:
|
||||
- login: VincentParedes
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/103889729?v=4
|
||||
url: https://github.com/VincentParedes
|
||||
- - login: getsentry
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1396951?v=4
|
||||
url: https://github.com/getsentry
|
||||
- - login: InesIvanova
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22920417?u=409882ec1df6dbd77455788bb383a8de223dbf6f&v=4
|
||||
url: https://github.com/InesIvanova
|
||||
- - login: SendCloud
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7831959?v=4
|
||||
url: https://github.com/SendCloud
|
||||
- login: qaas
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8503759?u=10a6b4391ad6ab4cf9487ce54e3fcb61322d1efc&v=4
|
||||
url: https://github.com/qaas
|
||||
- login: mercedes-benz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4
|
||||
url: https://github.com/mercedes-benz
|
||||
- login: xoflare
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/74335107?v=4
|
||||
url: https://github.com/xoflare
|
||||
@@ -59,48 +53,57 @@ sponsors:
|
||||
- login: BoostryJP
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4
|
||||
url: https://github.com/BoostryJP
|
||||
- - login: nnfuzzy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/687670?v=4
|
||||
url: https://github.com/nnfuzzy
|
||||
- login: johnadjei
|
||||
- - login: johnadjei
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/767860?v=4
|
||||
url: https://github.com/johnadjei
|
||||
- login: HiredScore
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3908850?v=4
|
||||
url: https://github.com/HiredScore
|
||||
- login: wdwinslow
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4
|
||||
url: https://github.com/wdwinslow
|
||||
- login: Trivie
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4
|
||||
url: https://github.com/Trivie
|
||||
- - login: moellenbeck
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/169372?v=4
|
||||
url: https://github.com/moellenbeck
|
||||
- login: AccentDesign
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2429332?v=4
|
||||
url: https://github.com/AccentDesign
|
||||
- login: RodneyU215
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3329665?u=ec6a9adf8e7e8e306eed7d49687c398608d1604f&v=4
|
||||
url: https://github.com/RodneyU215
|
||||
- login: tizz98
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5739698?u=f095a3659e3a8e7c69ccd822696990b521ea25f9&v=4
|
||||
url: https://github.com/tizz98
|
||||
- login: dorianturba
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9381120?u=4bfc7032a824d1ed1994aa8256dfa597c8f187ad&v=4
|
||||
url: https://github.com/dorianturba
|
||||
- login: jmaralc
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/21101214?u=b15a9f07b7cbf6c9dcdbcb6550bbd2c52f55aa50&v=4
|
||||
url: https://github.com/jmaralc
|
||||
- login: marutoraman
|
||||
- login: takashi-yoneya
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4
|
||||
url: https://github.com/marutoraman
|
||||
- login: leynier
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/36774373?u=2284831c821307de562ebde5b59014d5416c7e0d&v=4
|
||||
url: https://github.com/leynier
|
||||
url: https://github.com/takashi-yoneya
|
||||
- login: mainframeindustries
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4
|
||||
url: https://github.com/mainframeindustries
|
||||
- login: A-Edge
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4
|
||||
url: https://github.com/A-Edge
|
||||
- login: DelfinaCare
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4
|
||||
url: https://github.com/DelfinaCare
|
||||
- - login: karelhusa
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11407706?u=4f787cffc30ea198b15935c751940f0b48a26a17&v=4
|
||||
url: https://github.com/karelhusa
|
||||
- - login: povilasb
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1213442?u=b11f58ed6ceea6e8297c9b310030478ebdac894d&v=4
|
||||
url: https://github.com/povilasb
|
||||
- login: primer-io
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4
|
||||
url: https://github.com/primer-io
|
||||
- - login: DucNgn
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43587865?u=a9f9f61569aebdc0ce74df85b8cc1a219a7ab570&v=4
|
||||
url: https://github.com/DucNgn
|
||||
- login: A-Edge
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4
|
||||
url: https://github.com/A-Edge
|
||||
- - login: Kludex
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
@@ -116,6 +119,15 @@ sponsors:
|
||||
- login: kamalgill
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/133923?u=0df9181d97436ce330e9acf90ab8a54b7022efe7&v=4
|
||||
url: https://github.com/kamalgill
|
||||
- login: gazpachoking
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/187133?v=4
|
||||
url: https://github.com/gazpachoking
|
||||
- login: dekoza
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/210980?u=c03c78a8ae1039b500dfe343665536ebc51979b2&v=4
|
||||
url: https://github.com/dekoza
|
||||
- login: pamelafox
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/297042?v=4
|
||||
url: https://github.com/pamelafox
|
||||
- login: deserat
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/299332?v=4
|
||||
url: https://github.com/deserat
|
||||
@@ -128,6 +140,9 @@ sponsors:
|
||||
- login: koxudaxi
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4
|
||||
url: https://github.com/koxudaxi
|
||||
- login: falkben
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
|
||||
url: https://github.com/falkben
|
||||
- login: jqueguiner
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/690878?u=bd65cc1f228ce6455e56dfaca3ef47c33bc7c3b0&v=4
|
||||
url: https://github.com/jqueguiner
|
||||
@@ -164,12 +179,21 @@ sponsors:
|
||||
- login: zsinx6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4
|
||||
url: https://github.com/zsinx6
|
||||
- login: anomaly
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4
|
||||
url: https://github.com/anomaly
|
||||
- login: bauyrzhanospan
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3536037?u=25c86201d0212497aefcc1688cccf509057a1dc4&v=4
|
||||
url: https://github.com/bauyrzhanospan
|
||||
- login: MarekBleschke
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3616870?v=4
|
||||
url: https://github.com/MarekBleschke
|
||||
- login: aacayaco
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3634801?u=eaadda178c964178fcb64886f6c732172c8f8219&v=4
|
||||
url: https://github.com/aacayaco
|
||||
- login: peterHoburg
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3860655?u=f55f47eb2d6a9b495e806ac5a044e3ae01ccc1fa&v=4
|
||||
url: https://github.com/peterHoburg
|
||||
- login: jgreys
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4136890?u=b579fd97033269a5e703ab509c7d5478b146cc2d&v=4
|
||||
url: https://github.com/jgreys
|
||||
- login: gorhack
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4
|
||||
url: https://github.com/gorhack
|
||||
@@ -179,23 +203,20 @@ sponsors:
|
||||
- login: oliverxchen
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4
|
||||
url: https://github.com/oliverxchen
|
||||
- login: CINOAdam
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4728508?u=76ef23f06ae7c604e009873bc27cf0ea9ba738c9&v=4
|
||||
url: https://github.com/CINOAdam
|
||||
- login: ScrimForever
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5040124?u=091ec38bfe16d6e762099e91309b59f248616a65&v=4
|
||||
url: https://github.com/ScrimForever
|
||||
- login: ennui93
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5300907?u=5b5452725ddb391b2caaebf34e05aba873591c3a&v=4
|
||||
url: https://github.com/ennui93
|
||||
- login: MacroPower
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5648814?u=e13991efd1e03c44c911f919872e750530ded633&v=4
|
||||
url: https://github.com/MacroPower
|
||||
- login: ternaus
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=fabc8d75c921b3380126adb5a931c5da6e7db04f&v=4
|
||||
url: https://github.com/ternaus
|
||||
- login: Yaleesa
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6135475?v=4
|
||||
url: https://github.com/Yaleesa
|
||||
- login: iwpnd
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6152183?u=b2286006daafff5f991557344fee20b5da59639a&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6152183?u=c485eefca5c6329600cae63dd35e4f5682ce6924&v=4
|
||||
url: https://github.com/iwpnd
|
||||
- login: simw
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6322526?v=4
|
||||
@@ -203,11 +224,8 @@ sponsors:
|
||||
- login: pkucmus
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6347418?u=98f5918b32e214a168a2f5d59b0b8ebdf57dca0d&v=4
|
||||
url: https://github.com/pkucmus
|
||||
- login: ioalloc
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6737824?u=6c3a31449f1c92064287171aa9ebe6363a0c9b7b&v=4
|
||||
url: https://github.com/ioalloc
|
||||
- login: s3ich4n
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6926298?u=ba3025d698e1c986655e776ae383a3d60d9d578e&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6926298?u=6690c5403bc1d9a1837886defdc5256e9a43b1db&v=4
|
||||
url: https://github.com/s3ich4n
|
||||
- login: Rehket
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7015688?u=3afb0ba200feebbc7f958950e92db34df2a3c172&v=4
|
||||
@@ -218,9 +236,9 @@ sponsors:
|
||||
- login: Shackelford-Arden
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7362263?v=4
|
||||
url: https://github.com/Shackelford-Arden
|
||||
- login: Vikka
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9381120?u=4bfc7032a824d1ed1994aa8256dfa597c8f187ad&v=4
|
||||
url: https://github.com/Vikka
|
||||
- login: wdwinslow
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4
|
||||
url: https://github.com/wdwinslow
|
||||
- login: Ge0f3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11887760?u=ccd80f1ac36dcb8517ef5c4e702e8cc5a80cad2f&v=4
|
||||
url: https://github.com/Ge0f3
|
||||
@@ -233,6 +251,9 @@ sponsors:
|
||||
- login: dannywade
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13680237?u=418ee985bd41577b20fde81417fb2d901e875e8a&v=4
|
||||
url: https://github.com/dannywade
|
||||
- login: khadrawy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13686061?u=59f25ef42ecf04c22657aac4238ce0e2d3d30304&v=4
|
||||
url: https://github.com/khadrawy
|
||||
- login: pablonnaoji
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/15187159?u=afc15bd5a4ba9c5c7206bbb1bcaeef606a0932e0&v=4
|
||||
url: https://github.com/pablonnaoji
|
||||
@@ -242,9 +263,6 @@ sponsors:
|
||||
- login: wedwardbeck
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/19333237?u=1de4ae2bf8d59eb4c013f21d863cbe0f2010575f&v=4
|
||||
url: https://github.com/wedwardbeck
|
||||
- login: stradivari96
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/19752586?u=255f5f06a768f518b20cebd6963e840ac49294fd&v=4
|
||||
url: https://github.com/stradivari96
|
||||
- login: RedCarpetUp
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/20360440?v=4
|
||||
url: https://github.com/RedCarpetUp
|
||||
@@ -266,33 +284,30 @@ sponsors:
|
||||
- login: veprimk
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/29689749?u=f8cb5a15a286e522e5b189bc572d5a1a90217fb2&v=4
|
||||
url: https://github.com/veprimk
|
||||
- login: meysam81
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/30233243?u=64dc9fc62d039892c6fb44d804251cad5537132b&v=4
|
||||
url: https://github.com/meysam81
|
||||
- login: BrettskiPy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/30988215?u=d8a94a67e140d5ee5427724b292cc52d8827087a&v=4
|
||||
url: https://github.com/BrettskiPy
|
||||
- login: mauroalejandrojm
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31569442?u=cdada990a1527926a36e95f62c30a8b48bbc49a1&v=4
|
||||
url: https://github.com/mauroalejandrojm
|
||||
- login: Leay15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4
|
||||
url: https://github.com/Leay15
|
||||
- login: ygorpontelo
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32963605?u=35f7103f9c4c4c2589ae5737ee882e9375ef072e&v=4
|
||||
url: https://github.com/ygorpontelo
|
||||
- login: AlrasheedA
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33544979?u=7fe66bf62b47682612b222e3e8f4795ef3be769b&v=4
|
||||
url: https://github.com/AlrasheedA
|
||||
- login: ProteinQure
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4
|
||||
url: https://github.com/ProteinQure
|
||||
- login: guligon90
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35070513?u=b48c05f669d1ea1d329f90dc70e45f10b569ef55&v=4
|
||||
url: https://github.com/guligon90
|
||||
- login: ybressler
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=41e2c00f1eebe3c402635f0325e41b4e6511462c&v=4
|
||||
url: https://github.com/ybressler
|
||||
- login: ddilidili
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/42176885?u=c0a849dde06987434653197b5f638d3deb55fc6c&v=4
|
||||
url: https://github.com/ddilidili
|
||||
- login: dbanty
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9bcce836bbce55835291c5b2ac93a4e311f4b3c3&v=4
|
||||
url: https://github.com/dbanty
|
||||
- login: VictorCalderon
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/44529243?u=cea69884f826a29aff1415493405209e0706d07a&v=4
|
||||
url: https://github.com/VictorCalderon
|
||||
@@ -305,24 +320,21 @@ sponsors:
|
||||
- login: dudikbender
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=494f85229115076121b3639a3806bbac1c6ae7f6&v=4
|
||||
url: https://github.com/dudikbender
|
||||
- login: daisuke8000
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/55035595?u=23a3f2f2925ad3efc27c7420041622b7f5fd2b79&v=4
|
||||
url: https://github.com/daisuke8000
|
||||
- login: dazeddd
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/59472056?u=7a1b668449bf8b448db13e4c575576d24d7d658b&v=4
|
||||
url: https://github.com/dazeddd
|
||||
- login: yakkonaut
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/60633704?u=90a71fd631aa998ba4a96480788f017c9904e07b&v=4
|
||||
url: https://github.com/yakkonaut
|
||||
- login: primer-io
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4
|
||||
url: https://github.com/primer-io
|
||||
- login: around
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62425723?v=4
|
||||
url: https://github.com/around
|
||||
- login: patsatsia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4
|
||||
url: https://github.com/patsatsia
|
||||
- login: predictionmachine
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63719559?v=4
|
||||
url: https://github.com/predictionmachine
|
||||
- login: minsau
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/64386242?u=7e45f24b2958caf946fa3546ea33bacf5cd886f8&v=4
|
||||
url: https://github.com/minsau
|
||||
- login: daverin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/70378377?u=6d1814195c0de7162820eaad95a25b423a3869c0&v=4
|
||||
url: https://github.com/daverin
|
||||
@@ -332,14 +344,20 @@ sponsors:
|
||||
- login: dotlas
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/88832003?v=4
|
||||
url: https://github.com/dotlas
|
||||
- login: programvx
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/96057906?v=4
|
||||
url: https://github.com/programvx
|
||||
- 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: linux-china
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/46711?v=4
|
||||
url: https://github.com/linux-china
|
||||
- login: ddanier
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/113563?v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4
|
||||
url: https://github.com/ddanier
|
||||
- login: jhb
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/142217?v=4
|
||||
@@ -350,8 +368,11 @@ sponsors:
|
||||
- login: bryanculbertson
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/144028?u=defda4f90e93429221cc667500944abde60ebe4a&v=4
|
||||
url: https://github.com/bryanculbertson
|
||||
- login: hhatto
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/150309?u=3e8f63c27bf996bfc68464b0ce3f7a3e40e6ea7f&v=4
|
||||
url: https://github.com/hhatto
|
||||
- login: yourkin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/178984?u=fa7c3503b47bf16405b96d21554bc59f07a65523&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/178984?u=b43a7e5f8818f7d9083d3b110118d9c27d48a794&v=4
|
||||
url: https://github.com/yourkin
|
||||
- login: slafs
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4
|
||||
@@ -369,14 +390,11 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/388564?v=4
|
||||
url: https://github.com/dmig
|
||||
- login: rinckd
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/546002?u=1fcc7e664dc86524a0af6837a0c222829c3fd4e5&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/546002?u=8ec88ab721a5636346f19dcd677a6f323058be8b&v=4
|
||||
url: https://github.com/rinckd
|
||||
- login: securancy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/606673?v=4
|
||||
url: https://github.com/securancy
|
||||
- login: falkben
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
|
||||
url: https://github.com/falkben
|
||||
- login: hardbyte
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/855189?u=aa29e92f34708814d6b67fcd47ca4cf2ce1c04ed&v=4
|
||||
url: https://github.com/hardbyte
|
||||
@@ -384,16 +402,16 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4
|
||||
url: https://github.com/browniebroke
|
||||
- login: janfilips
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/870699?u=6034d81731ecb41ae5c717e56a901ed46fc039a8&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/870699?u=50de77b93d3a0b06887e672d4e8c7b9d643085aa&v=4
|
||||
url: https://github.com/janfilips
|
||||
- login: woodrad
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1410765?u=86707076bb03d143b3b11afc1743d2aa496bd8bf&v=4
|
||||
url: https://github.com/woodrad
|
||||
- login: Pytlicek
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1430522?u=169dba3bfbc04ed214a914640ff435969f19ddb3&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1430522?u=01b1f2f7671ce3131e0877d08e2e3f8bdbb0a38a&v=4
|
||||
url: https://github.com/Pytlicek
|
||||
- login: allen0125
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1448456?u=d4feb3d06a61baa4a69857ce371cc53fb4dffd2c&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1448456?u=dc2ad819497eef494b88688a1796e0adb87e7cae&v=4
|
||||
url: https://github.com/allen0125
|
||||
- login: WillHogan
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=7036c064cf29781470573865264ec8e60b6b809f&v=4
|
||||
@@ -401,9 +419,9 @@ sponsors:
|
||||
- login: cbonoz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2351087?u=fd3e8030b2cc9fbfbb54a65e9890c548a016f58b&v=4
|
||||
url: https://github.com/cbonoz
|
||||
- login: rglsk
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2768101?u=e349c88673f2155fe021331377c656a9d74bcc25&v=4
|
||||
url: https://github.com/rglsk
|
||||
- login: Debakel
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2857237?u=07df6d11c8feef9306d071cb1c1005a2dd596585&v=4
|
||||
url: https://github.com/Debakel
|
||||
- login: paul121
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3116995?u=6e2d8691cc345e63ee02e4eb4d7cef82b1fcbedc&v=4
|
||||
url: https://github.com/paul121
|
||||
@@ -413,9 +431,15 @@ sponsors:
|
||||
- login: anthonycorletti
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3477132?v=4
|
||||
url: https://github.com/anthonycorletti
|
||||
- login: jonathanhle
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3851599?u=76b9c5d2fecd6c3a16e7645231878c4507380d4d&v=4
|
||||
url: https://github.com/jonathanhle
|
||||
- login: pawamoy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4
|
||||
url: https://github.com/pawamoy
|
||||
- login: nikeee
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4068864?u=63f8eee593f25138e0f1032ef442e9ad24907d4c&v=4
|
||||
url: https://github.com/nikeee
|
||||
- login: Alisa-lisa
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4
|
||||
url: https://github.com/Alisa-lisa
|
||||
@@ -423,17 +447,23 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4
|
||||
url: https://github.com/danielunderwood
|
||||
- login: unredundant
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5607577?u=57dd0023365bec03f4fc566df6b81bc0a264a47d&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5607577?u=1ffbf39f5bb8736b75c0d235707d6e8f803725c5&v=4
|
||||
url: https://github.com/unredundant
|
||||
- login: Baghdady92
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5708590?v=4
|
||||
url: https://github.com/Baghdady92
|
||||
- login: holec
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6438041?u=f5af71ec85b3a9d7b8139cb5af0512b02fa9ab1e&v=4
|
||||
url: https://github.com/holec
|
||||
- login: mattwelke
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7719209?u=5d963ead289969257190b133250653bd99df06ba&v=4
|
||||
url: https://github.com/mattwelke
|
||||
- login: hcristea
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7814406?u=61d7a4fcf846983a4606788eac25e1c6c1209ba8&v=4
|
||||
url: https://github.com/hcristea
|
||||
- login: moonape1226
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4
|
||||
url: https://github.com/moonape1226
|
||||
- login: davanstrien
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8995957?u=fb2aad2b52bb4e7b56db6d7c8ecc9ae1eac1b984&v=4
|
||||
url: https://github.com/davanstrien
|
||||
- login: yenchenLiu
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9199638?u=8cdf5ae507448430d90f6f3518d1665a23afe99b&v=4
|
||||
url: https://github.com/yenchenLiu
|
||||
@@ -449,30 +479,33 @@ sponsors:
|
||||
- login: satwikkansal
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10217535?u=b12d6ef74ea297de9e46da6933b1a5b7ba9e6a61&v=4
|
||||
url: https://github.com/satwikkansal
|
||||
- login: mntolia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10390224?v=4
|
||||
url: https://github.com/mntolia
|
||||
- login: pheanex
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10408624?u=5b6bab6ee174aa6e991333e06eb29f628741013d&v=4
|
||||
url: https://github.com/pheanex
|
||||
- login: JimFawkes
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12075115?u=dc58ecfd064d72887c34bf500ddfd52592509acd&v=4
|
||||
url: https://github.com/JimFawkes
|
||||
- login: giuliano-oliveira
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13181797?u=0ef2dfbf7fc9a9726d45c21d32b5d1038a174870&v=4
|
||||
url: https://github.com/giuliano-oliveira
|
||||
- login: logan-connolly
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16244943?u=8ae66dfbba936463cc8aa0dd7a6d2b4c0cc757eb&v=4
|
||||
url: https://github.com/logan-connolly
|
||||
- login: sanghunka
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16280020?u=960f5426ae08303229f045b9cc2ed463dcd41c15&v=4
|
||||
url: https://github.com/sanghunka
|
||||
- login: stevenayers
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16361214?u=098b797d8d48afb8cd964b717847943b61d24a6d&v=4
|
||||
url: https://github.com/stevenayers
|
||||
- login: cdsre
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16945936?v=4
|
||||
url: https://github.com/cdsre
|
||||
- login: aprilcoskun
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/17393603?u=29145243b4c7fadc80c7099471309cc2c04b6bcc&v=4
|
||||
url: https://github.com/aprilcoskun
|
||||
- login: jangia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/17927101?u=9261b9bb0c3e3bb1ecba43e8915dc58d8c9a077e&v=4
|
||||
url: https://github.com/jangia
|
||||
- login: paulowiz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/18649504?u=d8a6ac40321f2bded0eba78b637751c7f86c6823&v=4
|
||||
url: https://github.com/paulowiz
|
||||
- login: yannicschroeer
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22749683?u=4df05a7296c207b91c5d7c7a11c29df5ab313e2b&v=4
|
||||
url: https://github.com/yannicschroeer
|
||||
@@ -482,18 +515,21 @@ sponsors:
|
||||
- login: fstau
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24669867?u=60e7c8c09f8dafabee8fc3edcd6f9e19abbff918&v=4
|
||||
url: https://github.com/fstau
|
||||
- login: pers0n4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24864600?u=444441027bc2c9f9db68e8047d65ff23d25699cf&v=4
|
||||
url: https://github.com/pers0n4
|
||||
- login: SebTota
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25122511?v=4
|
||||
url: https://github.com/SebTota
|
||||
- login: mertguvencli
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/29762151?u=16a906d90df96c8cff9ea131a575c4bc171b1523&v=4
|
||||
url: https://github.com/mertguvencli
|
||||
- login: elisoncrum
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/30413278?u=531190845bb0935dbc1e4f017cda3cb7b4dd0e54&v=4
|
||||
url: https://github.com/elisoncrum
|
||||
- login: ruizdiazever
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/29817086?u=2df54af55663d246e3a4dc8273711c37f1adb117&v=4
|
||||
url: https://github.com/ruizdiazever
|
||||
- login: HosamAlmoghraby
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32025281?u=aa1b09feabccbf9dc506b81c71155f32d126cefa&v=4
|
||||
url: https://github.com/HosamAlmoghraby
|
||||
- login: kitaramu0401
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33246506?u=929e6efa2c518033b8097ba524eb5347a069bb3b&v=4
|
||||
url: https://github.com/kitaramu0401
|
||||
- login: engineerjoe440
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4
|
||||
url: https://github.com/engineerjoe440
|
||||
@@ -501,7 +537,7 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/36180226?v=4
|
||||
url: https://github.com/declon
|
||||
- login: alvarobartt
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/36760800?u=ac9ccb8b9164eb5fe7d5276142591aa1b8080daf&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/36760800?u=9b38695807eb981d452989699ff72ec2d8f6508e&v=4
|
||||
url: https://github.com/alvarobartt
|
||||
- login: d-e-h-i-o
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/36816716?v=4
|
||||
@@ -516,11 +552,14 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/42189572?u=a2d6121bac4d125d92ec207460fa3f1842d37e66&v=4
|
||||
url: https://github.com/ilias-ant
|
||||
- login: arrrrrmin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43553423?u=fee5739394fea074cb0b66929d070114a5067aae&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43553423?u=2a812c1a2ec58227ed01778837f255143de9df97&v=4
|
||||
url: https://github.com/arrrrrmin
|
||||
- login: BomGard
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/47395385?u=8e9052f54e0b8dc7285099c438fa29c55a7d6407&v=4
|
||||
url: https://github.com/BomGard
|
||||
- login: MauriceKuenicke
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/47433175?u=37455bc95c7851db296ac42626f0cacb77ca2443&v=4
|
||||
url: https://github.com/MauriceKuenicke
|
||||
- login: hgalytoby
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=f4888c2c54929bd86eed0d3971d09fcb306e5088&v=4
|
||||
url: https://github.com/hgalytoby
|
||||
- login: akanz1
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/51492342?u=2280f57134118714645e16b535c1a37adf6b369b&v=4
|
||||
url: https://github.com/akanz1
|
||||
@@ -548,24 +587,24 @@ sponsors:
|
||||
- login: alessio-proietti
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/67370599?u=8ac73db1e18e946a7681f173abdb640516f88515&v=4
|
||||
url: https://github.com/alessio-proietti
|
||||
- login: Mr-Sunglasses
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/81439109?u=a5d0762fdcec26e18a028aef05323de3c6fb195c&v=4
|
||||
url: https://github.com/Mr-Sunglasses
|
||||
- - login: backbord
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6814946?v=4
|
||||
url: https://github.com/backbord
|
||||
- login: pondDevThai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/71592181?u=08af9a59bccfd8f6b101de1005aa9822007d0a44&v=4
|
||||
url: https://github.com/pondDevThai
|
||||
- login: marlonmartins2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/87719558?u=d07ffecfdabf4fd9aca987f8b5cd9128c65e598e&v=4
|
||||
url: https://github.com/marlonmartins2
|
||||
- - login: 2niuhe
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13382324?u=ac918d72e0329c87ba29b3bf85e03e98a4ee9427&v=4
|
||||
url: https://github.com/2niuhe
|
||||
- login: gabrielmbmb
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=6d1e00b5d558e96718312ff910a2318f47cc3145&v=4
|
||||
url: https://github.com/gabrielmbmb
|
||||
- login: danburonline
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34251194?u=2cad4388c1544e539ecb732d656e42fb07b4ff2d&v=4
|
||||
url: https://github.com/danburonline
|
||||
- login: zachspar
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41600414?u=edf29c197137f51bace3f19a2ba759662640771f&v=4
|
||||
url: https://github.com/zachspar
|
||||
- login: sownt
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/44340502?u=c06e3c45fb00a403075172770805fe57ff17b1cf&v=4
|
||||
url: https://github.com/sownt
|
||||
- login: aahouzi
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/75032370?u=82677ee9cd86b3ccf4e13d9cb6765d8de5713e1e&v=4
|
||||
url: https://github.com/aahouzi
|
||||
- login: Moises6669
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/66188523?u=96af25b8d5be9f983cb96e9dd7c605c716caf1f5&v=4
|
||||
url: https://github.com/Moises6669
|
||||
- login: su-shubham
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/75021117?v=4
|
||||
url: https://github.com/su-shubham
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
maintainers:
|
||||
- login: tiangolo
|
||||
answers: 1248
|
||||
prs: 318
|
||||
answers: 1315
|
||||
prs: 342
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=740f11212a731f56798f558ceddb0bd07642afa7&v=4
|
||||
url: https://github.com/tiangolo
|
||||
experts:
|
||||
- login: Kludex
|
||||
count: 352
|
||||
count: 367
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: dmontagu
|
||||
@@ -15,12 +15,16 @@ experts:
|
||||
url: https://github.com/dmontagu
|
||||
- login: ycd
|
||||
count: 221
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=fa40e037060d62bf82e16b505d870a2866725f38&v=4
|
||||
url: https://github.com/ycd
|
||||
- login: Mause
|
||||
count: 207
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
|
||||
url: https://github.com/Mause
|
||||
- login: JarroVGIT
|
||||
count: 187
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
|
||||
url: https://github.com/JarroVGIT
|
||||
- login: euri10
|
||||
count: 166
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
|
||||
@@ -33,38 +37,38 @@ experts:
|
||||
count: 77
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
|
||||
url: https://github.com/raphaelauv
|
||||
- login: iudeen
|
||||
count: 76
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
|
||||
url: https://github.com/iudeen
|
||||
- login: ArcLightSlavik
|
||||
count: 71
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
|
||||
url: https://github.com/ArcLightSlavik
|
||||
- login: JarroVGIT
|
||||
count: 68
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
|
||||
url: https://github.com/JarroVGIT
|
||||
- login: falkben
|
||||
count: 58
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
|
||||
url: https://github.com/falkben
|
||||
- login: sm-Fifteen
|
||||
count: 49
|
||||
count: 50
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4
|
||||
url: https://github.com/sm-Fifteen
|
||||
- login: insomnes
|
||||
count: 46
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
|
||||
url: https://github.com/insomnes
|
||||
- login: jgould22
|
||||
count: 46
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
|
||||
url: https://github.com/jgould22
|
||||
- login: Dustyposa
|
||||
count: 43
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4
|
||||
url: https://github.com/Dustyposa
|
||||
- login: adriangb
|
||||
count: 40
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=81f0262df34e1460ca546fbd0c211169c2478532&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=75087f0cf0e9f725f3cd18a899218b6c63ae60d3&v=4
|
||||
url: https://github.com/adriangb
|
||||
- login: jgould22
|
||||
count: 40
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
|
||||
url: https://github.com/jgould22
|
||||
- login: includeamin
|
||||
count: 39
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4
|
||||
@@ -73,6 +77,10 @@ experts:
|
||||
count: 37
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4
|
||||
url: https://github.com/STeveShary
|
||||
- login: chbndrhnns
|
||||
count: 35
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
|
||||
url: https://github.com/chbndrhnns
|
||||
- login: prostomarkeloff
|
||||
count: 33
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4
|
||||
@@ -81,26 +89,22 @@ experts:
|
||||
count: 31
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4
|
||||
url: https://github.com/frankie567
|
||||
- login: acidjunk
|
||||
count: 31
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
|
||||
url: https://github.com/acidjunk
|
||||
- login: krishnardt
|
||||
count: 31
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4
|
||||
url: https://github.com/krishnardt
|
||||
- login: chbndrhnns
|
||||
count: 30
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
|
||||
url: https://github.com/chbndrhnns
|
||||
- login: wshayes
|
||||
count: 29
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
|
||||
url: https://github.com/wshayes
|
||||
- login: panla
|
||||
count: 27
|
||||
count: 29
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4
|
||||
url: https://github.com/panla
|
||||
- login: acidjunk
|
||||
count: 25
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
|
||||
url: https://github.com/acidjunk
|
||||
- login: ghandic
|
||||
count: 25
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4
|
||||
@@ -113,6 +117,10 @@ experts:
|
||||
count: 24
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4
|
||||
url: https://github.com/SirTelemak
|
||||
- login: odiseo0
|
||||
count: 23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=16f9255804161c6ff3c8b7ef69848f0126bcd405&v=4
|
||||
url: https://github.com/odiseo0
|
||||
- login: acnebs
|
||||
count: 22
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=c27e50269f1ef8ea950cc6f0268c8ec5cebbe9c9&v=4
|
||||
@@ -129,10 +137,6 @@ experts:
|
||||
count: 19
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4
|
||||
url: https://github.com/retnikt
|
||||
- login: odiseo0
|
||||
count: 19
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4
|
||||
url: https://github.com/odiseo0
|
||||
- login: Hultner
|
||||
count: 18
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4
|
||||
@@ -157,6 +161,10 @@ experts:
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
|
||||
url: https://github.com/waynerv
|
||||
- login: yinziyan1206
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4
|
||||
url: https://github.com/yinziyan1206
|
||||
- login: dstlny
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4
|
||||
@@ -171,7 +179,7 @@ experts:
|
||||
url: https://github.com/hellocoldworld
|
||||
- login: haizaar
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/58201?u=4f1f9843d69433ca0d380d95146cfe119e5fdac4&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/58201?u=dd40d99a3e1935d0b768f122bfe2258d6ea53b2b&v=4
|
||||
url: https://github.com/haizaar
|
||||
- login: valentin994
|
||||
count: 13
|
||||
@@ -181,47 +189,31 @@ experts:
|
||||
count: 12
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/17401854?u=474680c02b94cba810cb9032fb7eb787d9cc9d22&v=4
|
||||
url: https://github.com/David-Lor
|
||||
- login: yinziyan1206
|
||||
count: 12
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4
|
||||
url: https://github.com/yinziyan1206
|
||||
- login: n8sty
|
||||
count: 12
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4
|
||||
url: https://github.com/n8sty
|
||||
- login: lowercase00
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/21188280?v=4
|
||||
url: https://github.com/lowercase00
|
||||
- login: zamiramir
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/40475662?u=e58ef61034e8d0d6a312cc956fb09b9c3332b449&v=4
|
||||
url: https://github.com/zamiramir
|
||||
- login: mbroton
|
||||
count: 12
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4
|
||||
url: https://github.com/mbroton
|
||||
last_month_active:
|
||||
- login: JarroVGIT
|
||||
count: 30
|
||||
count: 18
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
|
||||
url: https://github.com/JarroVGIT
|
||||
- login: zoliknemet
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4
|
||||
url: https://github.com/zoliknemet
|
||||
- login: iudeen
|
||||
count: 5
|
||||
count: 8
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
|
||||
url: https://github.com/iudeen
|
||||
- login: Kludex
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: odiseo0
|
||||
- login: mbroton
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4
|
||||
url: https://github.com/odiseo0
|
||||
- login: jonatasoli
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4
|
||||
url: https://github.com/mbroton
|
||||
- login: yinziyan1206
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4
|
||||
url: https://github.com/jonatasoli
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4
|
||||
url: https://github.com/yinziyan1206
|
||||
top_contributors:
|
||||
- login: waynerv
|
||||
count: 25
|
||||
@@ -236,9 +228,17 @@ top_contributors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
|
||||
url: https://github.com/dmontagu
|
||||
- login: jaystone776
|
||||
count: 15
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4
|
||||
url: https://github.com/jaystone776
|
||||
- login: Kludex
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: dependabot
|
||||
count: 14
|
||||
avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4
|
||||
url: https://github.com/apps/dependabot
|
||||
- login: euri10
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
|
||||
@@ -247,10 +247,6 @@ top_contributors:
|
||||
count: 12
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4
|
||||
url: https://github.com/mariacamilagl
|
||||
- login: Kludex
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: Smlep
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
|
||||
@@ -267,6 +263,14 @@ top_contributors:
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
|
||||
url: https://github.com/hard-coders
|
||||
- login: rjNemo
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
|
||||
url: https://github.com/rjNemo
|
||||
- login: pre-commit-ci
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4
|
||||
url: https://github.com/apps/pre-commit-ci
|
||||
- login: wshayes
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
|
||||
@@ -279,21 +283,25 @@ top_contributors:
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4
|
||||
url: https://github.com/Attsun1031
|
||||
- login: dependabot
|
||||
- login: ComicShrimp
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4
|
||||
url: https://github.com/apps/dependabot
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=f440bc9062afb3c43b9b9c6cdfdcfe31d58699ef&v=4
|
||||
url: https://github.com/ComicShrimp
|
||||
- login: jekirl
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2546697?u=a027452387d85bd4a14834e19d716c99255fb3b7&v=4
|
||||
url: https://github.com/jekirl
|
||||
- login: samuelcolvin
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=807390ba9cfe23906c3bf8a0d56aaca3cf2bfa0d&v=4
|
||||
url: https://github.com/samuelcolvin
|
||||
- login: jfunez
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/805749?v=4
|
||||
url: https://github.com/jfunez
|
||||
- login: ycd
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=fa40e037060d62bf82e16b505d870a2866725f38&v=4
|
||||
url: https://github.com/ycd
|
||||
- login: komtaki
|
||||
count: 4
|
||||
@@ -307,21 +315,29 @@ top_contributors:
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
|
||||
url: https://github.com/lsglucas
|
||||
- login: ComicShrimp
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=b3e4d9a14d9a65d429ce62c566aef73178b7111d&v=4
|
||||
url: https://github.com/ComicShrimp
|
||||
- login: NinaHwang
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
|
||||
url: https://github.com/NinaHwang
|
||||
- login: batlopes
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4
|
||||
url: https://github.com/batlopes
|
||||
top_reviewers:
|
||||
- login: Kludex
|
||||
count: 95
|
||||
count: 108
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: BilalAlpaslan
|
||||
count: 65
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4
|
||||
url: https://github.com/BilalAlpaslan
|
||||
- login: yezz123
|
||||
count: 56
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
|
||||
url: https://github.com/yezz123
|
||||
- login: tokusumi
|
||||
count: 49
|
||||
count: 50
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
|
||||
url: https://github.com/tokusumi
|
||||
- login: waynerv
|
||||
@@ -332,22 +348,18 @@ top_reviewers:
|
||||
count: 47
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/59285379?v=4
|
||||
url: https://github.com/Laineyzhang55
|
||||
- login: BilalAlpaslan
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4
|
||||
url: https://github.com/BilalAlpaslan
|
||||
- login: ycd
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=fa40e037060d62bf82e16b505d870a2866725f38&v=4
|
||||
url: https://github.com/ycd
|
||||
- login: cikay
|
||||
count: 41
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24587499?u=e772190a051ab0eaa9c8542fcff1892471638f2b&v=4
|
||||
url: https://github.com/cikay
|
||||
- login: yezz123
|
||||
- login: JarroVGIT
|
||||
count: 34
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
|
||||
url: https://github.com/yezz123
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
|
||||
url: https://github.com/JarroVGIT
|
||||
- login: AdrianDeAnda
|
||||
count: 33
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=b2ea249c6b41ddf98679c8d110d0f67d4a3ebf93&v=4
|
||||
@@ -356,10 +368,18 @@ top_reviewers:
|
||||
count: 31
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
|
||||
url: https://github.com/ArcLightSlavik
|
||||
- login: iudeen
|
||||
count: 26
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
|
||||
url: https://github.com/iudeen
|
||||
- login: cassiobotaro
|
||||
count: 25
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4
|
||||
url: https://github.com/cassiobotaro
|
||||
- login: lsglucas
|
||||
count: 25
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
|
||||
url: https://github.com/lsglucas
|
||||
- login: dmontagu
|
||||
count: 23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
|
||||
@@ -369,21 +389,21 @@ top_reviewers:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4
|
||||
url: https://github.com/komtaki
|
||||
- login: hard-coders
|
||||
count: 19
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
|
||||
url: https://github.com/hard-coders
|
||||
- login: 0417taehyun
|
||||
count: 19
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4
|
||||
url: https://github.com/0417taehyun
|
||||
- login: lsglucas
|
||||
count: 18
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
|
||||
url: https://github.com/lsglucas
|
||||
- login: JarroVGIT
|
||||
count: 18
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
|
||||
url: https://github.com/JarroVGIT
|
||||
- login: rjNemo
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
|
||||
url: https://github.com/rjNemo
|
||||
- login: Smlep
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
|
||||
url: https://github.com/Smlep
|
||||
- login: zy7y
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/67154681?u=5d634834cc514028ea3f9115f7030b99a1f4d5a4&v=4
|
||||
@@ -396,14 +416,6 @@ top_reviewers:
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4
|
||||
url: https://github.com/SwftAlpc
|
||||
- login: rjNemo
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
|
||||
url: https://github.com/rjNemo
|
||||
- login: Smlep
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
|
||||
url: https://github.com/Smlep
|
||||
- login: DevDae
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/87962045?u=08e10fa516e844934f4b3fc7c38b33c61697e4a1&v=4
|
||||
@@ -416,6 +428,10 @@ top_reviewers:
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63476957?u=6c86e59b48e0394d4db230f37fc9ad4d7e2c27c7&v=4
|
||||
url: https://github.com/delhi09
|
||||
- login: odiseo0
|
||||
count: 14
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=16f9255804161c6ff3c8b7ef69848f0126bcd405&v=4
|
||||
url: https://github.com/odiseo0
|
||||
- login: sh0nk
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6478810?u=af15d724875cec682ed8088a86d36b2798f981c0&v=4
|
||||
@@ -424,6 +440,10 @@ top_reviewers:
|
||||
count: 12
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=efb5b45b55584450507834f279ce48d4d64dea2f&v=4
|
||||
url: https://github.com/RunningIkkyu
|
||||
- login: LorhanSohaky
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4
|
||||
url: https://github.com/LorhanSohaky
|
||||
- login: solomein-sv
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/46193920?u=46acfb4aeefb1d7b9fdc5a8cbd9eb8744683c47a&v=4
|
||||
@@ -440,13 +460,13 @@ top_reviewers:
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7887703?v=4
|
||||
url: https://github.com/maoyibo
|
||||
- login: odiseo0
|
||||
- login: ComicShrimp
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4
|
||||
url: https://github.com/odiseo0
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=f440bc9062afb3c43b9b9c6cdfdcfe31d58699ef&v=4
|
||||
url: https://github.com/ComicShrimp
|
||||
- login: graingert
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/413772?v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/413772?u=64b77b6aa405c68a9c6bcf45f84257c66eea5f32&v=4
|
||||
url: https://github.com/graingert
|
||||
- login: PandaHun
|
||||
count: 9
|
||||
@@ -460,6 +480,10 @@ top_reviewers:
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4
|
||||
url: https://github.com/bezaca
|
||||
- login: izaguerreiro
|
||||
count: 8
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2241504?v=4
|
||||
url: https://github.com/izaguerreiro
|
||||
- login: raphaelauv
|
||||
count: 8
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
|
||||
@@ -472,10 +496,6 @@ top_reviewers:
|
||||
count: 8
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5690226?v=4
|
||||
url: https://github.com/rogerbrinkmann
|
||||
- login: ComicShrimp
|
||||
count: 8
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=b3e4d9a14d9a65d429ce62c566aef73178b7111d&v=4
|
||||
url: https://github.com/ComicShrimp
|
||||
- login: NinaHwang
|
||||
count: 8
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
|
||||
@@ -488,6 +508,10 @@ top_reviewers:
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
|
||||
url: https://github.com/Serrones
|
||||
- login: jovicon
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/21287303?u=b049eac3e51a4c0473c2efe66b4d28a7d8f2b572&v=4
|
||||
url: https://github.com/jovicon
|
||||
- login: ryuckel
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/36391432?u=094eec0cfddd5013f76f31e55e56147d78b19553&v=4
|
||||
@@ -496,19 +520,3 @@ top_reviewers:
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8245071?u=b3afd005f9e4bf080c219ef61a592b3a8004b764&v=4
|
||||
url: https://github.com/NastasiaSaby
|
||||
- login: Mause
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
|
||||
url: https://github.com/Mause
|
||||
- login: wakabame
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35513518?v=4
|
||||
url: https://github.com/wakabame
|
||||
- login: AlexandreBiguet
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1483079?u=ff926455cd4cab03c6c49441aa5dc2b21df3e266&v=4
|
||||
url: https://github.com/AlexandreBiguet
|
||||
- login: krocdort
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34248814?v=4
|
||||
url: https://github.com/krocdort
|
||||
|
||||
@@ -8,9 +8,6 @@ gold:
|
||||
- url: https://cryptapi.io/
|
||||
title: "CryptAPI: Your easy to use, secure and privacy oriented payment gateway."
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/cryptapi.svg
|
||||
- url: https://app.imgwhale.xyz/
|
||||
title: The ultimate solution to unlimited and forever cloud storage.
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/imgwhale.svg
|
||||
- url: https://doist.com/careers/9B437B1615-wa-senior-backend-engineer-python
|
||||
title: Help us migrate doist to FastAPI
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/doist.svg
|
||||
|
||||
@@ -23,7 +23,7 @@ Each of those response `dict`s can have a key `model`, containing a Pydantic mod
|
||||
|
||||
For example, to declare another response with a status code `404` and a Pydantic model `Message`, you can write:
|
||||
|
||||
```Python hl_lines="18 23"
|
||||
```Python hl_lines="18 22"
|
||||
{!../../../docs_src/additional_responses/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -26,13 +26,23 @@ The important difference for us is that with HTTPX we are not limited to synchro
|
||||
|
||||
## Example
|
||||
|
||||
For a simple example, let's consider the following `main.py` module:
|
||||
For a simple example, let's consider a file structure similar to the one described in [Bigger Applications](../tutorial/bigger-applications.md){.internal-link target=_blank} and [Testing](../tutorial/testing.md){.internal-link target=_blank}:
|
||||
|
||||
```
|
||||
.
|
||||
├── app
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py
|
||||
│ └── test_main.py
|
||||
```
|
||||
|
||||
The file `main.py` would have:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/async_tests/main.py!}
|
||||
```
|
||||
|
||||
The `test_main.py` module that contains the tests for `main.py` could look like this now:
|
||||
The file `test_main.py` would have the tests for `main.py`, it could look like this now:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/async_tests/test_main.py!}
|
||||
|
||||
@@ -21,6 +21,12 @@ For example, if you are squeezing performance, you can install and use <a href="
|
||||
|
||||
Import the `Response` class (sub-class) you want to use and declare it in the *path operation decorator*.
|
||||
|
||||
For large responses, returning a `Response` directly is much faster than returning a dictionary.
|
||||
|
||||
This is because by default, FastAPI will inspect every item inside and make sure it is serializable with JSON, using the same [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank} explained in the tutorial. This is what allows you to return **arbitrary objects**, for example database models.
|
||||
|
||||
But if you are certain that the content that you are returning is **serializable with JSON**, you can pass it directly to the response class and avoid the extra overhead that FastAPI would have by passing your return content through the `jsonable_encoder` before passing it to the response class.
|
||||
|
||||
```Python hl_lines="2 7"
|
||||
{!../../../docs_src/custom_response/tutorial001b.py!}
|
||||
```
|
||||
@@ -244,6 +250,36 @@ You can also use the `response_class` parameter:
|
||||
|
||||
In this case, you can return the file path directly from your *path operation* function.
|
||||
|
||||
## Custom response class
|
||||
|
||||
You can create your own custom response class, inheriting from `Response` and using it.
|
||||
|
||||
For example, let's say that you want to use <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a>, but with some custom settings not used in the included `ORJSONResponse` class.
|
||||
|
||||
Let's say you want it to return indented and formatted JSON, so you want to use the orjson option `orjson.OPT_INDENT_2`.
|
||||
|
||||
You could create a `CustomORJSONResponse`. The main thing you have to do is create a `Response.render(content)` method that returns the content as `bytes`:
|
||||
|
||||
```Python hl_lines="9-14 17"
|
||||
{!../../../docs_src/custom_response/tutorial009c.py!}
|
||||
```
|
||||
|
||||
Now instead of returning:
|
||||
|
||||
```json
|
||||
{"message": "Hello World"}
|
||||
```
|
||||
|
||||
...this response will return:
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Hello World"
|
||||
}
|
||||
```
|
||||
|
||||
Of course, you will probably find much better ways to take advantage of this than formatting JSON. 😉
|
||||
|
||||
## Default response class
|
||||
|
||||
When creating a **FastAPI** class instance or an `APIRouter` you can specify which response class to use by default.
|
||||
|
||||
@@ -8,7 +8,7 @@ But FastAPI also supports using <a href="https://docs.python.org/3/library/datac
|
||||
{!../../../docs_src/dataclasses/tutorial001.py!}
|
||||
```
|
||||
|
||||
This is still thanks to **Pydantic**, as it has <a href="https://pydantic-docs.helpmanual.io/usage/dataclasses/#use-of-stdlib-dataclasses-with-basemodel" class="external-link" target="_blank">internal support for `dataclasses`</a>.
|
||||
This is still supported thanks to **Pydantic**, as it has <a href="https://pydantic-docs.helpmanual.io/usage/dataclasses/#use-of-stdlib-dataclasses-with-basemodel" class="external-link" target="_blank">internal support for `dataclasses`</a>.
|
||||
|
||||
So, even with the code above that doesn't use Pydantic explicitly, FastAPI is using Pydantic to convert those standard dataclasses to Pydantic's own flavor of dataclasses.
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ It will have a *path operation* that will receive an `Invoice` body, and a query
|
||||
|
||||
This part is pretty normal, most of the code is probably already familiar to you:
|
||||
|
||||
```Python hl_lines="10-14 37-54"
|
||||
```Python hl_lines="9-13 36-53"
|
||||
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -83,7 +83,7 @@ So we are going to use that same knowledge to document how the *external API* sh
|
||||
|
||||
First create a new `APIRouter` that will contain one or more callbacks.
|
||||
|
||||
```Python hl_lines="5 26"
|
||||
```Python hl_lines="3 25"
|
||||
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -96,7 +96,7 @@ It should look just like a normal FastAPI *path operation*:
|
||||
* It should probably have a declaration of the body it should receive, e.g. `body: InvoiceEvent`.
|
||||
* And it could also have a declaration of the response it should return, e.g. `response_model=InvoiceEventReceived`.
|
||||
|
||||
```Python hl_lines="17-19 22-23 29-33"
|
||||
```Python hl_lines="16-18 21-22 28-32"
|
||||
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -163,7 +163,7 @@ At this point you have the *callback path operation(s)* needed (the one(s) that
|
||||
|
||||
Now use the parameter `callbacks` in *your API's path operation decorator* to pass the attribute `.routes` (that's actually just a `list` of routes/*path operations*) from that callback router:
|
||||
|
||||
```Python hl_lines="36"
|
||||
```Python hl_lines="35"
|
||||
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -34,13 +34,19 @@ Here's a more complete example.
|
||||
|
||||
Use a dependency to check if the username and password are correct.
|
||||
|
||||
For this, use the Python standard module <a href="https://docs.python.org/3/library/secrets.html" class="external-link" target="_blank">`secrets`</a> to check the username and password:
|
||||
For this, use the Python standard module <a href="https://docs.python.org/3/library/secrets.html" class="external-link" target="_blank">`secrets`</a> to check the username and password.
|
||||
|
||||
```Python hl_lines="1 11-13"
|
||||
`secrets.compare_digest()` needs to take `bytes` or a `str` that only contains ASCII characters (the ones in English), this means it wouldn't work with characters like `á`, as in `Sebastián`.
|
||||
|
||||
To handle that, we first convert the `username` and `password` to `bytes` encoding them with UTF-8.
|
||||
|
||||
Then we can use `secrets.compare_digest()` to ensure that `credentials.username` is `"stanleyjobson"`, and that `credentials.password` is `"swordfish"`.
|
||||
|
||||
```Python hl_lines="1 11-21"
|
||||
{!../../../docs_src/security/tutorial007.py!}
|
||||
```
|
||||
|
||||
This will ensure that `credentials.username` is `"stanleyjobson"`, and that `credentials.password` is `"swordfish"`. This would be similar to:
|
||||
This would be similar to:
|
||||
|
||||
```Python
|
||||
if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"):
|
||||
@@ -102,6 +108,6 @@ That way, using `secrets.compare_digest()` in your application code, it will be
|
||||
|
||||
After detecting that the credentials are incorrect, return an `HTTPException` with a status code 401 (the same returned when no credentials are provided) and add the header `WWW-Authenticate` to make the browser show the login prompt again:
|
||||
|
||||
```Python hl_lines="15-19"
|
||||
```Python hl_lines="23-27"
|
||||
{!../../../docs_src/security/tutorial007.py!}
|
||||
```
|
||||
|
||||
@@ -123,7 +123,7 @@ That's why when talking about version 2.0 it's common to say "Swagger", and for
|
||||
|
||||
There are several Flask REST frameworks, but after investing the time and work into investigating them, I found that many are discontinued or abandoned, with several standing issues that made them unfit.
|
||||
|
||||
### <a href="https://marshmallow.readthedocs.io/en/3.0/" class="external-link" target="_blank">Marshmallow</a>
|
||||
### <a href="https://marshmallow.readthedocs.io/en/stable/" class="external-link" target="_blank">Marshmallow</a>
|
||||
|
||||
One of the main features needed by API systems is data "<abbr title="also called marshalling, conversion">serialization</abbr>" which is taking data from the code (Python) and converting it into something that can be sent through the network. For example, converting an object containing data from a database into a JSON object. Converting `datetime` objects into strings, etc.
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ async def read_results():
|
||||
|
||||
---
|
||||
|
||||
If you are using a third party library that communicates with something (a database, an API, the file system, etc) and doesn't have support for using `await`, (this is currently the case for most database libraries), then declare your *path operation functions* as normally, with just `def`, like:
|
||||
If you are using a third party library that communicates with something (a database, an API, the file system, etc.) and doesn't have support for using `await`, (this is currently the case for most database libraries), then declare your *path operation functions* as normally, with just `def`, like:
|
||||
|
||||
```Python hl_lines="2"
|
||||
@app.get('/')
|
||||
@@ -45,7 +45,7 @@ If you just don't know, use normal `def`.
|
||||
|
||||
---
|
||||
|
||||
**Note**: you can mix `def` and `async def` in your *path operation functions* as much as you need and define each one using the best option for you. FastAPI will do the right thing with them.
|
||||
**Note**: You can mix `def` and `async def` in your *path operation functions* as much as you need and define each one using the best option for you. FastAPI will do the right thing with them.
|
||||
|
||||
Anyway, in any of the cases above, FastAPI will still work asynchronously and be extremely fast.
|
||||
|
||||
@@ -397,23 +397,23 @@ All that is what powers FastAPI (through Starlette) and what makes it have such
|
||||
|
||||
These are very technical details of how **FastAPI** works underneath.
|
||||
|
||||
If you have quite some technical knowledge (co-routines, threads, blocking, etc) and are curious about how FastAPI handles `async def` vs normal `def`, go ahead.
|
||||
If you have quite some technical knowledge (co-routines, threads, blocking, etc.) and are curious about how FastAPI handles `async def` vs normal `def`, go ahead.
|
||||
|
||||
### Path operation functions
|
||||
|
||||
When you declare a *path operation function* with normal `def` instead of `async def`, it is run in an external threadpool that is then awaited, instead of being called directly (as it would block the server).
|
||||
|
||||
If you are coming from another async framework that does not work in the way described above and you are used to define trivial compute-only *path operation functions* with plain `def` for a tiny performance gain (about 100 nanoseconds), please note that in **FastAPI** the effect would be quite opposite. In these cases, it's better to use `async def` unless your *path operation functions* use code that performs blocking <abbr title="Input/Output: disk reading or writing, network communications.">I/O</abbr>.
|
||||
If you are coming from another async framework that does not work in the way described above and you are used to defining trivial compute-only *path operation functions* with plain `def` for a tiny performance gain (about 100 nanoseconds), please note that in **FastAPI** the effect would be quite opposite. In these cases, it's better to use `async def` unless your *path operation functions* use code that performs blocking <abbr title="Input/Output: disk reading or writing, network communications.">I/O</abbr>.
|
||||
|
||||
Still, in both situations, chances are that **FastAPI** will [still be faster](/#performance){.internal-link target=_blank} than (or at least comparable to) your previous framework.
|
||||
|
||||
### Dependencies
|
||||
|
||||
The same applies for dependencies. If a dependency is a standard `def` function instead of `async def`, it is run in the external threadpool.
|
||||
The same applies for [dependencies](/tutorial/dependencies/index.md){.internal-link target=_blank}. If a dependency is a standard `def` function instead of `async def`, it is run in the external threadpool.
|
||||
|
||||
### Sub-dependencies
|
||||
|
||||
You can have multiple dependencies and sub-dependencies requiring each other (as parameters of the function definitions), some of them might be created with `async def` and some with normal `def`. It would still work, and the ones created with normal `def` would be called on an external thread (from the threadpool) instead of being "awaited".
|
||||
You can have multiple dependencies and [sub-dependencies](/tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} requiring each other (as parameters of the function definitions), some of them might be created with `async def` and some with normal `def`. It would still work, and the ones created with normal `def` would be called on an external thread (from the threadpool) instead of being "awaited".
|
||||
|
||||
### Other utility functions
|
||||
|
||||
|
||||
@@ -84,58 +84,36 @@ To check it worked, use:
|
||||
|
||||
If it shows the `pip` binary at `env/bin/pip` then it worked. 🎉
|
||||
|
||||
|
||||
|
||||
!!! tip
|
||||
Every time you install a new package with `pip` under that environment, activate the environment again.
|
||||
|
||||
This makes sure that if you use a terminal program installed by that package (like `flit`), you use the one from your local environment and not any other that could be installed globally.
|
||||
|
||||
### Flit
|
||||
|
||||
**FastAPI** uses <a href="https://flit.readthedocs.io/en/latest/index.html" class="external-link" target="_blank">Flit</a> to build, package and publish the project.
|
||||
|
||||
After activating the environment as described above, install `flit`:
|
||||
Make sure you have the latest pip version on your virtual environment to avoid errors on the next steps:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install flit
|
||||
$ python -m pip install --upgrade pip
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Now re-activate the environment to make sure you are using the `flit` you just installed (and not a global one).
|
||||
!!! tip
|
||||
Every time you install a new package with `pip` under that environment, activate the environment again.
|
||||
|
||||
And now use `flit` to install the development dependencies:
|
||||
This makes sure that if you use a terminal program installed by that package, you use the one from your local environment and not any other that could be installed globally.
|
||||
|
||||
=== "Linux, macOS"
|
||||
### pip
|
||||
|
||||
<div class="termy">
|
||||
After activating the environment as described above:
|
||||
|
||||
```console
|
||||
$ flit install --deps develop --symlink
|
||||
<div class="termy">
|
||||
|
||||
---> 100%
|
||||
```
|
||||
```console
|
||||
$ pip install -e ."[dev,doc,test]"
|
||||
|
||||
</div>
|
||||
---> 100%
|
||||
```
|
||||
|
||||
=== "Windows"
|
||||
|
||||
If you are on Windows, use `--pth-file` instead of `--symlink`:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ flit install --deps develop --pth-file
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
It will install all the dependencies and your local FastAPI in your local environment.
|
||||
|
||||
@@ -143,7 +121,7 @@ It will install all the dependencies and your local FastAPI in your local enviro
|
||||
|
||||
If you create a Python file that imports and uses FastAPI, and run it with the Python from your local environment, it will use your local FastAPI source code.
|
||||
|
||||
And if you update that local FastAPI source code, as it is installed with `--symlink` (or `--pth-file` on Windows), when you run that Python file again, it will use the fresh version of FastAPI you just edited.
|
||||
And if you update that local FastAPI source code, as it is installed with `-e`, when you run that Python file again, it will use the fresh version of FastAPI you just edited.
|
||||
|
||||
That way, you don't have to "install" your local version to be able to test every change.
|
||||
|
||||
@@ -161,7 +139,7 @@ $ bash scripts/format.sh
|
||||
|
||||
It will also auto-sort all your imports.
|
||||
|
||||
For it to sort them correctly, you need to have FastAPI installed locally in your environment, with the command in the section above using `--symlink` (or `--pth-file` on Windows).
|
||||
For it to sort them correctly, you need to have FastAPI installed locally in your environment, with the command in the section above using `-e`.
|
||||
|
||||
## Docs
|
||||
|
||||
|
||||
@@ -195,6 +195,6 @@ With **FastAPI** you get all of **Pydantic**'s features (as FastAPI is based on
|
||||
* Use of hierarchical Pydantic models, Python `typing`’s `List` and `Dict`, etc.
|
||||
* And validators allow complex data schemas to be clearly and easily defined, checked and documented as JSON Schema.
|
||||
* You can have deeply **nested JSON** objects and have them all validated and annotated.
|
||||
* **Extendible**:
|
||||
* **Extensible**:
|
||||
* Pydantic allows custom data types to be defined or you can extend validation with methods on a model decorated with the validator decorator.
|
||||
* 100% test coverage.
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
@@ -8,8 +8,8 @@
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg?event=push&branch=master" alt="Test">
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage">
|
||||
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://coverage-badge.samuelcolvin.workers.dev/tiangolo/fastapi.svg" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
@@ -27,12 +27,11 @@
|
||||
|
||||
---
|
||||
|
||||
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
|
||||
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.7+ based on standard Python type hints.
|
||||
|
||||
The key features are:
|
||||
|
||||
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance).
|
||||
|
||||
* **Fast to code**: Increase the speed to develop features by about 200% to 300%. *
|
||||
* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. *
|
||||
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
|
||||
@@ -110,7 +109,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
|
||||
|
||||
## Requirements
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI stands on the shoulders of giants:
|
||||
|
||||
@@ -129,7 +128,7 @@ $ pip install fastapi
|
||||
|
||||
</div>
|
||||
|
||||
You will also need an ASGI server, for production such as <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
You will also need an ASGI server, for production such as <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
@@ -326,7 +325,7 @@ You do that with standard modern Python types.
|
||||
|
||||
You don't have to learn a new syntax, the methods or classes of a specific library, etc.
|
||||
|
||||
Just standard **Python 3.6+**.
|
||||
Just standard **Python 3.7+**.
|
||||
|
||||
For example, for an `int`:
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ The syntax using `typing` is **compatible** with all versions, from Python 3.6 t
|
||||
|
||||
As Python advances, **newer versions** come with improved support for these type annotations and in many cases you won't even need to import and use the `typing` module to declare the type annotations.
|
||||
|
||||
If you can chose a more recent version of Python for your project, you will be able to take advantage of that extra simplicity. See some examples below.
|
||||
If you can choose a more recent version of Python for your project, you will be able to take advantage of that extra simplicity. See some examples below.
|
||||
|
||||
#### List
|
||||
|
||||
@@ -372,7 +372,7 @@ These types that take type parameters in square brackets are called **Generic ty
|
||||
|
||||
=== "Python 3.9 and above"
|
||||
|
||||
You can use the same builtin types as generics (with square brakets and types inside):
|
||||
You can use the same builtin types as generics (with square brackets and types inside):
|
||||
|
||||
* `list`
|
||||
* `tuple`
|
||||
@@ -387,7 +387,7 @@ These types that take type parameters in square brackets are called **Generic ty
|
||||
|
||||
=== "Python 3.10 and above"
|
||||
|
||||
You can use the same builtin types as generics (with square brakets and types inside):
|
||||
You can use the same builtin types as generics (with square brackets and types inside):
|
||||
|
||||
* `list`
|
||||
* `tuple`
|
||||
|
||||
@@ -3,6 +3,236 @@
|
||||
## Latest Changes
|
||||
|
||||
|
||||
## 0.86.0
|
||||
|
||||
### Features
|
||||
|
||||
* ⬆ Add Python 3.11 to the officially supported versions. PR [#5587](https://github.com/tiangolo/fastapi/pull/5587) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ✅ Enable tests for Python 3.11. PR [#4881](https://github.com/tiangolo/fastapi/pull/4881) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Fixes
|
||||
|
||||
* 🐛 Close FormData (uploaded files) after the request is done. PR [#5465](https://github.com/tiangolo/fastapi/pull/5465) by [@adriangb](https://github.com/adriangb).
|
||||
|
||||
### Docs
|
||||
|
||||
* ✏ Fix typo in `docs/en/docs/tutorial/security/oauth2-jwt.md`. PR [#5584](https://github.com/tiangolo/fastapi/pull/5584) by [@vivekashok1221](https://github.com/vivekashok1221).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Update wording in Chinese translation for `docs/zh/docs/python-types.md`. PR [#5416](https://github.com/tiangolo/fastapi/pull/5416) by [@supercaizehua](https://github.com/supercaizehua).
|
||||
* 🌐 Add Russian translation for `docs/ru/docs/deployment/index.md`. PR [#5336](https://github.com/tiangolo/fastapi/pull/5336) by [@Xewus](https://github.com/Xewus).
|
||||
* 🌐 Update Chinese translation for `docs/tutorial/security/oauth2-jwt.md`. PR [#3846](https://github.com/tiangolo/fastapi/pull/3846) by [@jaystone776](https://github.com/jaystone776).
|
||||
|
||||
### Internal
|
||||
|
||||
* 👷 Update FastAPI People to exclude bots: pre-commit-ci, dependabot. PR [#5586](https://github.com/tiangolo/fastapi/pull/5586) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🎨 Format OpenAPI JSON in `test_starlette_exception.py`. PR [#5379](https://github.com/tiangolo/fastapi/pull/5379) by [@iudeen](https://github.com/iudeen).
|
||||
* 👷 Switch from Codecov to Smokeshow plus pytest-cov to pure coverage for internal tests. PR [#5583](https://github.com/tiangolo/fastapi/pull/5583) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👥 Update FastAPI People. PR [#5571](https://github.com/tiangolo/fastapi/pull/5571) by [@github-actions[bot]](https://github.com/apps/github-actions).
|
||||
|
||||
## 0.85.2
|
||||
|
||||
### Docs
|
||||
|
||||
* ✏ Fix grammar and add helpful links to dependencies in `docs/en/docs/async.md`. PR [#5432](https://github.com/tiangolo/fastapi/pull/5432) by [@pamelafox](https://github.com/pamelafox).
|
||||
* ✏ Fix broken link in `alternatives.md`. PR [#5455](https://github.com/tiangolo/fastapi/pull/5455) by [@su-shubham](https://github.com/su-shubham).
|
||||
* ✏ Fix typo in docs about contributing, for compatibility with `pip` in Zsh. PR [#5523](https://github.com/tiangolo/fastapi/pull/5523) by [@zhangbo2012](https://github.com/zhangbo2012).
|
||||
* 📝 Fix typo in docs with examples for Python 3.10 instead of 3.9. PR [#5545](https://github.com/tiangolo/fastapi/pull/5545) by [@feliciss](https://github.com/feliciss).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/request-forms.md`. PR [#4934](https://github.com/tiangolo/fastapi/pull/4934) by [@batlopes](https://github.com/batlopes).
|
||||
* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md`. PR [#4971](https://github.com/tiangolo/fastapi/pull/4971) by [@Zssaer](https://github.com/Zssaer).
|
||||
* 🌐 Add French translation for `deployment/deta.md`. PR [#3692](https://github.com/tiangolo/fastapi/pull/3692) by [@rjNemo](https://github.com/rjNemo).
|
||||
* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/query-params-str-validations.md`. PR [#5255](https://github.com/tiangolo/fastapi/pull/5255) by [@hjlarry](https://github.com/hjlarry).
|
||||
* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/sql-databases.md`. PR [#4999](https://github.com/tiangolo/fastapi/pull/4999) by [@Zssaer](https://github.com/Zssaer).
|
||||
* 🌐 Add Chinese translation for `docs/zh/docs/advanced/wsgi.md`. PR [#4505](https://github.com/tiangolo/fastapi/pull/4505) by [@ASpathfinder](https://github.com/ASpathfinder).
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/body-multiple-params.md`. PR [#4111](https://github.com/tiangolo/fastapi/pull/4111) by [@lbmendes](https://github.com/lbmendes).
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/path-params-numeric-validations.md`. PR [#4099](https://github.com/tiangolo/fastapi/pull/4099) by [@lbmendes](https://github.com/lbmendes).
|
||||
* 🌐 Add French translation for `deployment/versions.md`. PR [#3690](https://github.com/tiangolo/fastapi/pull/3690) by [@rjNemo](https://github.com/rjNemo).
|
||||
* 🌐 Add French translation for `docs/fr/docs/help-fastapi.md`. PR [#2233](https://github.com/tiangolo/fastapi/pull/2233) by [@JulianMaurin](https://github.com/JulianMaurin).
|
||||
* 🌐 Fix typo in Chinese translation for `docs/zh/docs/tutorial/security/first-steps.md`. PR [#5530](https://github.com/tiangolo/fastapi/pull/5530) by [@yuki1sntSnow](https://github.com/yuki1sntSnow).
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/response-status-code.md`. PR [#4922](https://github.com/tiangolo/fastapi/pull/4922) by [@batlopes](https://github.com/batlopes).
|
||||
* 🔧 Add config for Tamil translations. PR [#5563](https://github.com/tiangolo/fastapi/pull/5563) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Internal
|
||||
|
||||
* ⬆ Bump internal dependency mypy from 0.971 to 0.982. PR [#5541](https://github.com/tiangolo/fastapi/pull/5541) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||
* ⬆ Bump nwtgck/actions-netlify from 1.2.3 to 1.2.4. PR [#5507](https://github.com/tiangolo/fastapi/pull/5507) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||
* ⬆ Bump internal dependency types-ujson from 5.4.0 to 5.5.0. PR [#5537](https://github.com/tiangolo/fastapi/pull/5537) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||
* ⬆ Bump dawidd6/action-download-artifact from 2.23.0 to 2.24.0. PR [#5508](https://github.com/tiangolo/fastapi/pull/5508) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||
* ⬆ Update internal dependency pytest-cov requirement from <4.0.0,>=2.12.0 to >=2.12.0,<5.0.0. PR [#5539](https://github.com/tiangolo/fastapi/pull/5539) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5536](https://github.com/tiangolo/fastapi/pull/5536) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
|
||||
* 🐛 Fix internal Trio test warnings. PR [#5547](https://github.com/tiangolo/fastapi/pull/5547) by [@samuelcolvin](https://github.com/samuelcolvin).
|
||||
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5408](https://github.com/tiangolo/fastapi/pull/5408) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
|
||||
* ⬆️ Upgrade Typer to include Rich in scripts for docs. PR [#5502](https://github.com/tiangolo/fastapi/pull/5502) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🐛 Fix calling `mkdocs` for languages as a subprocess to fix/enable MkDocs Material search plugin. PR [#5501](https://github.com/tiangolo/fastapi/pull/5501) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.85.1
|
||||
|
||||
### Fixes
|
||||
|
||||
* 🐛 Fix support for strings in OpenAPI status codes: `default`, `1XX`, `2XX`, `3XX`, `4XX`, `5XX`. PR [#5187](https://github.com/tiangolo/fastapi/pull/5187) by [@JarroVGIT](https://github.com/JarroVGIT).
|
||||
|
||||
### Docs
|
||||
|
||||
* 📝 Add WayScript x FastAPI Tutorial to External Links section. PR [#5407](https://github.com/tiangolo/fastapi/pull/5407) by [@moneeka](https://github.com/moneeka).
|
||||
|
||||
### Internal
|
||||
|
||||
* 👥 Update FastAPI People. PR [#5447](https://github.com/tiangolo/fastapi/pull/5447) by [@github-actions[bot]](https://github.com/apps/github-actions).
|
||||
* 🔧 Disable Material for MkDocs search plugin. PR [#5495](https://github.com/tiangolo/fastapi/pull/5495) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔇 Ignore Trio warning in tests for CI. PR [#5483](https://github.com/tiangolo/fastapi/pull/5483) by [@samuelcolvin](https://github.com/samuelcolvin).
|
||||
|
||||
## 0.85.0
|
||||
|
||||
### Features
|
||||
|
||||
* ⬆ Upgrade version required of Starlette from `0.19.1` to `0.20.4`. Initial PR [#4820](https://github.com/tiangolo/fastapi/pull/4820) by [@Kludex](https://github.com/Kludex).
|
||||
* This includes several bug fixes in Starlette.
|
||||
* ⬆️ Upgrade Uvicorn max version in public extras: all. From `>=0.12.0,<0.18.0` to `>=0.12.0,<0.19.0`. PR [#5401](https://github.com/tiangolo/fastapi/pull/5401) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Internal
|
||||
|
||||
* ⬆️ Upgrade dependencies for doc and dev internal extras: Typer, Uvicorn. PR [#5400](https://github.com/tiangolo/fastapi/pull/5400) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ⬆️ Upgrade test dependencies: Black, HTTPX, databases, types-ujson. PR [#5399](https://github.com/tiangolo/fastapi/pull/5399) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ⬆️ Upgrade mypy and tweak internal type annotations. PR [#5398](https://github.com/tiangolo/fastapi/pull/5398) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Update test dependencies, upgrade Pytest, move dependencies from dev to test. PR [#5396](https://github.com/tiangolo/fastapi/pull/5396) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.84.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
This version of FastAPI drops support for Python 3.6. 🔥 Please upgrade to a supported version of Python (3.7 or above), Python 3.6 reached the end-of-life a long time ago. 😅☠
|
||||
|
||||
* 🔧 Update package metadata, drop support for Python 3.6, move build internals from Flit to Hatch. PR [#5240](https://github.com/tiangolo/fastapi/pull/5240) by [@ofek](https://github.com/ofek).
|
||||
|
||||
## 0.83.0
|
||||
|
||||
🚨 This is probably the last release (or one of the last releases) to support Python 3.6. 🔥
|
||||
|
||||
Python 3.6 reached the [end-of-life and is no longer supported by Python](https://www.python.org/downloads/release/python-3615/) since around a year ago.
|
||||
|
||||
You hopefully updated to a supported version of Python a while ago. If you haven't, you really should.
|
||||
|
||||
### Features
|
||||
|
||||
* ✨ Add support in `jsonable_encoder` for include and exclude with dataclasses. PR [#4923](https://github.com/tiangolo/fastapi/pull/4923) by [@DCsunset](https://github.com/DCsunset).
|
||||
|
||||
### Fixes
|
||||
|
||||
* 🐛 Fix `RuntimeError` raised when `HTTPException` has a status code with no content. PR [#5365](https://github.com/tiangolo/fastapi/pull/5365) by [@iudeen](https://github.com/iudeen).
|
||||
* 🐛 Fix empty reponse body when default `status_code` is empty but the a `Response` parameter with `response.status_code` is set. PR [#5360](https://github.com/tiangolo/fastapi/pull/5360) by [@tmeckel](https://github.com/tmeckel).
|
||||
|
||||
### Docs
|
||||
|
||||
* 📝 Update `SECURITY.md`. PR [#5377](https://github.com/tiangolo/fastapi/pull/5377) by [@Kludex](https://github.com/Kludex).
|
||||
|
||||
### Internal
|
||||
|
||||
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5352](https://github.com/tiangolo/fastapi/pull/5352) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
|
||||
|
||||
## 0.82.0
|
||||
|
||||
🚨 This is probably the last release (or one of the last releases) to support Python 3.6. 🔥
|
||||
|
||||
Python 3.6 reached the [end-of-life and is no longer supported by Python](https://www.python.org/downloads/release/python-3615/) since around a year ago.
|
||||
|
||||
You hopefully updated to a supported version of Python a while ago. If you haven't, you really should.
|
||||
|
||||
### Features
|
||||
|
||||
* ✨ Export `WebSocketState` in `fastapi.websockets`. PR [#4376](https://github.com/tiangolo/fastapi/pull/4376) by [@matiuszka](https://github.com/matiuszka).
|
||||
* ✨ Support Python internal description on Pydantic model's docstring. PR [#3032](https://github.com/tiangolo/fastapi/pull/3032) by [@Kludex](https://github.com/Kludex).
|
||||
* ✨ Update `ORJSONResponse` to support non `str` keys and serializing Numpy arrays. PR [#3892](https://github.com/tiangolo/fastapi/pull/3892) by [@baby5](https://github.com/baby5).
|
||||
|
||||
### Fixes
|
||||
|
||||
* 🐛 Allow exit code for dependencies with `yield` to always execute, by removing capacity limiter for them, to e.g. allow closing DB connections without deadlocks. PR [#5122](https://github.com/tiangolo/fastapi/pull/5122) by [@adriangb](https://github.com/adriangb).
|
||||
* 🐛 Fix FastAPI People GitHub Action: set HTTPX timeout for GraphQL query request. PR [#5222](https://github.com/tiangolo/fastapi/pull/5222) by [@iudeen](https://github.com/iudeen).
|
||||
* 🐛 Make sure a parameter defined as required is kept required in OpenAPI even if defined as optional in another dependency. PR [#4319](https://github.com/tiangolo/fastapi/pull/4319) by [@cd17822](https://github.com/cd17822).
|
||||
* 🐛 Fix support for path parameters in WebSockets. PR [#3879](https://github.com/tiangolo/fastapi/pull/3879) by [@davidbrochart](https://github.com/davidbrochart).
|
||||
|
||||
### Docs
|
||||
|
||||
* ✏ Update Hypercorn link, now pointing to GitHub. PR [#5346](https://github.com/tiangolo/fastapi/pull/5346) by [@baconfield](https://github.com/baconfield).
|
||||
* ✏ Tweak wording in `docs/en/docs/advanced/dataclasses.md`. PR [#3698](https://github.com/tiangolo/fastapi/pull/3698) by [@pfackeldey](https://github.com/pfackeldey).
|
||||
* 📝 Add note about Python 3.10 `X | Y` operator in explanation about Response Models. PR [#5307](https://github.com/tiangolo/fastapi/pull/5307) by [@MendyLanda](https://github.com/MendyLanda).
|
||||
* 📝 Add link to New Relic article: "How to monitor FastAPI application performance using Python agent". PR [#5260](https://github.com/tiangolo/fastapi/pull/5260) by [@sjyothi54](https://github.com/sjyothi54).
|
||||
* 📝 Update docs for `ORJSONResponse` with details about improving performance. PR [#2615](https://github.com/tiangolo/fastapi/pull/2615) by [@falkben](https://github.com/falkben).
|
||||
* 📝 Add docs for creating a custom Response class. PR [#5331](https://github.com/tiangolo/fastapi/pull/5331) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 📝 Add tip about using alias for form data fields. PR [#5329](https://github.com/tiangolo/fastapi/pull/5329) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Add Russian translation for `docs/ru/docs/features.md`. PR [#5315](https://github.com/tiangolo/fastapi/pull/5315) by [@Xewus](https://github.com/Xewus).
|
||||
* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/request-files.md`. PR [#4529](https://github.com/tiangolo/fastapi/pull/4529) by [@ASpathfinder](https://github.com/ASpathfinder).
|
||||
* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/encoder.md`. PR [#4969](https://github.com/tiangolo/fastapi/pull/4969) by [@Zssaer](https://github.com/Zssaer).
|
||||
* 🌐 Fix MkDocs file line for Portuguese translation of `background-task.md`. PR [#5242](https://github.com/tiangolo/fastapi/pull/5242) by [@ComicShrimp](https://github.com/ComicShrimp).
|
||||
|
||||
### Internal
|
||||
|
||||
* 👥 Update FastAPI People. PR [#5347](https://github.com/tiangolo/fastapi/pull/5347) by [@github-actions[bot]](https://github.com/apps/github-actions).
|
||||
* ⬆ Bump dawidd6/action-download-artifact from 2.22.0 to 2.23.0. PR [#5321](https://github.com/tiangolo/fastapi/pull/5321) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5318](https://github.com/tiangolo/fastapi/pull/5318) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
|
||||
* ✏ Fix a small code highlight line error. PR [#5256](https://github.com/tiangolo/fastapi/pull/5256) by [@hjlarry](https://github.com/hjlarry).
|
||||
* ♻ Internal small refactor, move `operation_id` parameter position in delete method for consistency with the code. PR [#4474](https://github.com/tiangolo/fastapi/pull/4474) by [@hiel](https://github.com/hiel).
|
||||
* 🔧 Update sponsors, disable ImgWhale. PR [#5338](https://github.com/tiangolo/fastapi/pull/5338) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.81.0
|
||||
|
||||
### Features
|
||||
|
||||
* ✨ Add ReDoc `<noscript>` warning when JS is disabled. PR [#5074](https://github.com/tiangolo/fastapi/pull/5074) by [@evroon](https://github.com/evroon).
|
||||
* ✨ Add support for `FrozenSet` in parameters (e.g. query). PR [#2938](https://github.com/tiangolo/fastapi/pull/2938) by [@juntatalor](https://github.com/juntatalor).
|
||||
* ✨ Allow custom middlewares to raise `HTTPException`s and propagate them. PR [#2036](https://github.com/tiangolo/fastapi/pull/2036) by [@ghandic](https://github.com/ghandic).
|
||||
* ✨ Preserve `json.JSONDecodeError` information when handling invalid JSON in request body, to support custom exception handlers that use its information. PR [#4057](https://github.com/tiangolo/fastapi/pull/4057) by [@UKnowWhoIm](https://github.com/UKnowWhoIm).
|
||||
|
||||
### Fixes
|
||||
|
||||
* 🐛 Fix `jsonable_encoder` for dataclasses with pydantic-compatible fields. PR [#3607](https://github.com/tiangolo/fastapi/pull/3607) by [@himbeles](https://github.com/himbeles).
|
||||
* 🐛 Fix support for extending `openapi_extras` with parameter lists. PR [#4267](https://github.com/tiangolo/fastapi/pull/4267) by [@orilevari](https://github.com/orilevari).
|
||||
|
||||
### Docs
|
||||
|
||||
* ✏ Fix a simple typo in `docs/en/docs/python-types.md`. PR [#5193](https://github.com/tiangolo/fastapi/pull/5193) by [@GlitchingCore](https://github.com/GlitchingCore).
|
||||
* ✏ Fix typos in `tests/test_schema_extra_examples.py`. PR [#5126](https://github.com/tiangolo/fastapi/pull/5126) by [@supraaxdd](https://github.com/supraaxdd).
|
||||
* ✏ Fix typos in `docs/en/docs/tutorial/path-params-numeric-validations.md`. PR [#5142](https://github.com/tiangolo/fastapi/pull/5142) by [@invisibleroads](https://github.com/invisibleroads).
|
||||
* 📝 Add step about upgrading pip in the venv to avoid errors when installing dependencies `docs/en/docs/contributing.md`. PR [#5181](https://github.com/tiangolo/fastapi/pull/5181) by [@edisnake](https://github.com/edisnake).
|
||||
* ✏ Reword and clarify text in tutorial `docs/en/docs/tutorial/body-nested-models.md`. PR [#5169](https://github.com/tiangolo/fastapi/pull/5169) by [@papb](https://github.com/papb).
|
||||
* ✏ Fix minor typo in `docs/en/docs/features.md`. PR [#5206](https://github.com/tiangolo/fastapi/pull/5206) by [@OtherBarry](https://github.com/OtherBarry).
|
||||
* ✏ Fix minor typos in `docs/en/docs/async.md`. PR [#5125](https://github.com/tiangolo/fastapi/pull/5125) by [@Ksenofanex](https://github.com/Ksenofanex).
|
||||
* 📝 Add external link to docs: "Fastapi, Docker(Docker compose) and Postgres". PR [#5033](https://github.com/tiangolo/fastapi/pull/5033) by [@krishnardt](https://github.com/krishnardt).
|
||||
* 📝 Simplify example for docs for Additional Responses, remove unnecessary `else`. PR [#4693](https://github.com/tiangolo/fastapi/pull/4693) by [@adriangb](https://github.com/adriangb).
|
||||
* 📝 Update docs, compare enums with identity instead of equality. PR [#4905](https://github.com/tiangolo/fastapi/pull/4905) by [@MicaelJarniac](https://github.com/MicaelJarniac).
|
||||
* ✏ Fix typo in `docs/en/docs/python-types.md`. PR [#4886](https://github.com/tiangolo/fastapi/pull/4886) by [@MicaelJarniac](https://github.com/MicaelJarniac).
|
||||
* 🎨 Fix syntax highlighting in docs for OpenAPI Callbacks. PR [#4368](https://github.com/tiangolo/fastapi/pull/4368) by [@xncbf](https://github.com/xncbf).
|
||||
* ✏ Reword confusing sentence in docs file `typo-fix-path-params-numeric-validations.md`. PR [#3219](https://github.com/tiangolo/fastapi/pull/3219) by [@ccrenfroe](https://github.com/ccrenfroe).
|
||||
* 📝 Update docs for handling HTTP Basic Auth with `secrets.compare_digest()` to account for non-ASCII characters. PR [#3536](https://github.com/tiangolo/fastapi/pull/3536) by [@lewoudar](https://github.com/lewoudar).
|
||||
* 📝 Update docs for testing, fix examples with relative imports. PR [#5302](https://github.com/tiangolo/fastapi/pull/5302) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Add Russian translation for `docs/ru/docs/index.md`. PR [#5289](https://github.com/tiangolo/fastapi/pull/5289) by [@impocode](https://github.com/impocode).
|
||||
* 🌐 Add Russian translation for `docs/ru/docs/deployment/versions.md`. PR [#4985](https://github.com/tiangolo/fastapi/pull/4985) by [@emp7yhead](https://github.com/emp7yhead).
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/header-params.md`. PR [#4921](https://github.com/tiangolo/fastapi/pull/4921) by [@batlopes](https://github.com/batlopes).
|
||||
* 🌐 Update `ko/mkdocs.yml` for a missing link. PR [#5020](https://github.com/tiangolo/fastapi/pull/5020) by [@dalinaum](https://github.com/dalinaum).
|
||||
|
||||
### Internal
|
||||
|
||||
* ⬆ Bump dawidd6/action-download-artifact from 2.21.1 to 2.22.0. PR [#5258](https://github.com/tiangolo/fastapi/pull/5258) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5196](https://github.com/tiangolo/fastapi/pull/5196) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
|
||||
* 🔥 Delete duplicated tests in `tests/test_tutorial/test_sql_databases/test_sql_databases.py`. PR [#5040](https://github.com/tiangolo/fastapi/pull/5040) by [@raccoonyy](https://github.com/raccoonyy).
|
||||
* ♻ Simplify internal RegEx in `fastapi/utils.py`. PR [#5057](https://github.com/tiangolo/fastapi/pull/5057) by [@pylounge](https://github.com/pylounge).
|
||||
* 🔧 Fix Type hint of `auto_error` which does not need to be `Optional[bool]`. PR [#4933](https://github.com/tiangolo/fastapi/pull/4933) by [@DavidKimDY](https://github.com/DavidKimDY).
|
||||
* 🔧 Update mypy config, use `strict = true` instead of manual configs. PR [#4605](https://github.com/tiangolo/fastapi/pull/4605) by [@michaeloliverx](https://github.com/michaeloliverx).
|
||||
* ♻ Change a `dict()` for `{}` in `fastapi/utils.py`. PR [#3138](https://github.com/tiangolo/fastapi/pull/3138) by [@ShahriyarR](https://github.com/ShahriyarR).
|
||||
* ♻ Move internal variable for errors in `jsonable_encoder` to put related code closer. PR [#4560](https://github.com/tiangolo/fastapi/pull/4560) by [@GuilleQP](https://github.com/GuilleQP).
|
||||
* ♻ Simplify conditional assignment in `fastapi/dependencies/utils.py`. PR [#4597](https://github.com/tiangolo/fastapi/pull/4597) by [@cikay](https://github.com/cikay).
|
||||
* ⬆ Upgrade version pin accepted for Flake8, for internal code, to `flake8 >=3.8.3,<6.0.0`. PR [#4097](https://github.com/tiangolo/fastapi/pull/4097) by [@jamescurtin](https://github.com/jamescurtin).
|
||||
* 🍱 Update Jina banner, fix typo. PR [#5301](https://github.com/tiangolo/fastapi/pull/5301) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.80.0
|
||||
|
||||
### Breaking Changes - Fixes
|
||||
|
||||
@@ -18,7 +18,7 @@ You can define an attribute to be a subtype. For example, a Python `list`:
|
||||
{!> ../../../docs_src/body_nested_models/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
This will make `tags` be a list of items. Although it doesn't declare the type of each of the items.
|
||||
This will make `tags` be a list, although it doesn't declare the type of the elements of the list.
|
||||
|
||||
## List fields with type parameter
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Path Parameters and Numeric Validations
|
||||
|
||||
The same way you can declare more validations and metadata for query parameters with `Query`, you can declare the same type of validations and metadata for path parameters with `Path`.
|
||||
In the same way that you can declare more validations and metadata for query parameters with `Query`, you can declare the same type of validations and metadata for path parameters with `Path`.
|
||||
|
||||
## Import Path
|
||||
|
||||
@@ -77,7 +77,7 @@ Python won't do anything with that `*`, but it will know that all the following
|
||||
|
||||
## Number validations: greater than or equal
|
||||
|
||||
With `Query` and `Path` (and other's you'll see later) you can declare string constraints, but also number constraints.
|
||||
With `Query` and `Path` (and others you'll see later) you can declare number constraints.
|
||||
|
||||
Here, with `ge=1`, `item_id` will need to be an integer number "`g`reater than or `e`qual" to `1`.
|
||||
|
||||
@@ -122,9 +122,9 @@ And you can also declare numeric validations:
|
||||
* `le`: `l`ess than or `e`qual
|
||||
|
||||
!!! info
|
||||
`Query`, `Path`, and others you will see later are subclasses of a common `Param` class (that you don't need to use).
|
||||
`Query`, `Path`, and other classes you will see later are subclasses of a common `Param` class.
|
||||
|
||||
And all of them share the same all these same parameters of additional validation and metadata you have seen.
|
||||
All of them share the same parameters for additional validation and metadata you have seen.
|
||||
|
||||
!!! note "Technical Details"
|
||||
When you import `Query`, `Path` and others from `fastapi`, they are actually functions.
|
||||
|
||||
@@ -216,7 +216,7 @@ To do that, you can declare that `None` is a valid type but still use `default=.
|
||||
|
||||
=== "Python 3.6 and above"
|
||||
|
||||
```Python hl_lines="8"
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/query_params_str_validations/tutorial006c.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ You can make a file optional by using standard type annotations and setting a de
|
||||
{!> ../../../docs_src/request_files/tutorial001_02.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 and above"
|
||||
=== "Python 3.10 and above"
|
||||
|
||||
```Python hl_lines="7 14"
|
||||
{!> ../../../docs_src/request_files/tutorial001_02_py310.py!}
|
||||
|
||||
@@ -27,7 +27,7 @@ For example, in one of the ways the OAuth2 specification can be used (called "pa
|
||||
|
||||
The <abbr title="specification">spec</abbr> requires the fields to be exactly named `username` and `password`, and to be sent as form fields, not JSON.
|
||||
|
||||
With `Form` you can declare the same metadata and validation as with `Body` (and `Query`, `Path`, `Cookie`).
|
||||
With `Form` you can declare the same configurations as with `Body` (and `Query`, `Path`, `Cookie`), including validation, examples, an alias (e.g. `user-name` instead of `username`), etc.
|
||||
|
||||
!!! info
|
||||
`Form` is a class that inherits directly from `Body`.
|
||||
|
||||
@@ -168,7 +168,7 @@ Your response model could have default values, like:
|
||||
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
* `description: Union[str, None] = None` has a default of `None`.
|
||||
* `description: Union[str, None] = None` (or `str | None = None` in Python 3.10) has a default of `None`.
|
||||
* `tax: float = 10.5` has a default of `10.5`.
|
||||
* `tags: List[str] = []` as a default of an empty list: `[]`.
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@ Call the endpoint `/users/me/`, you will get the response as:
|
||||
|
||||
<img src="/img/tutorial/security/image09.png">
|
||||
|
||||
If you open the developer tools, you could see how the data sent and only includes the token, the password is only sent in the first request to authenticate the user and get that access token, but not afterwards:
|
||||
If you open the developer tools, you could see how the data sent only includes the token, the password is only sent in the first request to authenticate the user and get that access token, but not afterwards:
|
||||
|
||||
<img src="/img/tutorial/security/image10.png">
|
||||
|
||||
|
||||
@@ -50,7 +50,17 @@ And your **FastAPI** application might also be composed of several files/modules
|
||||
|
||||
### **FastAPI** app file
|
||||
|
||||
Let's say you have a file `main.py` with your **FastAPI** app:
|
||||
Let's say you have a file structure as described in [Bigger Applications](./bigger-applications.md){.internal-link target=_blank}:
|
||||
|
||||
```
|
||||
.
|
||||
├── app
|
||||
│ ├── __init__.py
|
||||
│ └── main.py
|
||||
```
|
||||
|
||||
In the file `main.py` you have your **FastAPI** app:
|
||||
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/app_testing/main.py!}
|
||||
@@ -58,18 +68,40 @@ Let's say you have a file `main.py` with your **FastAPI** app:
|
||||
|
||||
### Testing file
|
||||
|
||||
Then you could have a file `test_main.py` with your tests, and import your `app` from the `main` module (`main.py`):
|
||||
Then you could have a file `test_main.py` with your tests. It could live on the same Python package (the same directory with a `__init__.py` file):
|
||||
|
||||
```Python
|
||||
``` hl_lines="5"
|
||||
.
|
||||
├── app
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py
|
||||
│ └── test_main.py
|
||||
```
|
||||
|
||||
Because this file is in the same package, you can use relative imports to import the object `app` from the `main` module (`main.py`):
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/app_testing/test_main.py!}
|
||||
```
|
||||
|
||||
...and have the code for the tests just like before.
|
||||
|
||||
## Testing: extended example
|
||||
|
||||
Now let's extend this example and add more details to see how to test different parts.
|
||||
|
||||
### Extended **FastAPI** app file
|
||||
|
||||
Let's continue with the same file structure as before:
|
||||
|
||||
```
|
||||
.
|
||||
├── app
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py
|
||||
│ └── test_main.py
|
||||
```
|
||||
|
||||
Let's say that now the file `main.py` with your **FastAPI** app has some other **path operations**.
|
||||
|
||||
It has a `GET` operation that could return an error.
|
||||
|
||||
@@ -40,12 +40,12 @@
|
||||
<img class="sponsor-image" src="/img/sponsors/cryptapi-banner.svg" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
<!-- <div class="item">
|
||||
<a title="The ultimate solution to unlimited and forever cloud storage." style="display: block; position: relative;" href="https://app.imgwhale.xyz/" target="_blank">
|
||||
<span class="sponsor-badge">sponsor</span>
|
||||
<img class="sponsor-image" src="/img/sponsors/imgwhale-banner.svg" />
|
||||
</a>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="item">
|
||||
<a title="Help us migrate doist to FastAPI" style="display: block; position: relative;" href="https://doist.com/careers/9B437B1615-wa-senior-backend-engineer-python" target="_blank">
|
||||
<span class="sponsor-badge">sponsor</span>
|
||||
|
||||
@@ -106,7 +106,7 @@ Si estás construyendo un app de <abbr title="Interfaz de línea de comandos en
|
||||
|
||||
## Requisitos
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI está sobre los hombros de gigantes:
|
||||
|
||||
|
||||
245
docs/fr/docs/deployment/deta.md
Normal file
245
docs/fr/docs/deployment/deta.md
Normal file
@@ -0,0 +1,245 @@
|
||||
# Déployer FastAPI sur Deta
|
||||
|
||||
Dans cette section, vous apprendrez à déployer facilement une application **FastAPI** sur <a href="https://www.deta.
|
||||
sh/?ref=fastapi" class="external-link" target="_blank">Deta</a> en utilisant le plan tarifaire gratuit. 🎁
|
||||
|
||||
Cela vous prendra environ **10 minutes**.
|
||||
|
||||
!!! info
|
||||
<a href="https://www.deta.sh/?ref=fastapi" class="external-link" target="_blank">Deta</a> sponsorise **FastAPI**. 🎉
|
||||
|
||||
## Une application **FastAPI** de base
|
||||
|
||||
* Créez un répertoire pour votre application, par exemple `./fastapideta/` et déplacez-vous dedans.
|
||||
|
||||
### Le code FastAPI
|
||||
|
||||
* Créer un fichier `main.py` avec :
|
||||
|
||||
```Python
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int):
|
||||
return {"item_id": item_id}
|
||||
```
|
||||
|
||||
### Dépendances
|
||||
|
||||
Maintenant, dans le même répertoire, créez un fichier `requirements.txt` avec :
|
||||
|
||||
```text
|
||||
fastapi
|
||||
```
|
||||
|
||||
!!! tip "Astuce"
|
||||
Il n'est pas nécessaire d'installer Uvicorn pour déployer sur Deta, bien qu'il soit probablement souhaitable de l'installer localement pour tester votre application.
|
||||
|
||||
### Structure du répertoire
|
||||
|
||||
Vous aurez maintenant un répertoire `./fastapideta/` avec deux fichiers :
|
||||
|
||||
```
|
||||
.
|
||||
└── main.py
|
||||
└── requirements.txt
|
||||
```
|
||||
|
||||
## Créer un compte gratuit sur Deta
|
||||
|
||||
Créez maintenant un <a href="https://www.deta.sh/?ref=fastapi" class="external-link" target="_blank">compte gratuit
|
||||
sur Deta</a>, vous avez juste besoin d'une adresse email et d'un mot de passe.
|
||||
|
||||
Vous n'avez même pas besoin d'une carte de crédit.
|
||||
|
||||
## Installer le CLI (Interface en Ligne de Commande)
|
||||
|
||||
Une fois que vous avez votre compte, installez le <abbr title="Command Line Interface application">CLI</abbr> de Deta :
|
||||
|
||||
=== "Linux, macOS"
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ curl -fsSL https://get.deta.dev/cli.sh | sh
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
=== "Windows PowerShell"
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ iwr https://get.deta.dev/cli.ps1 -useb | iex
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Après l'avoir installé, ouvrez un nouveau terminal afin que la nouvelle installation soit détectée.
|
||||
|
||||
Dans un nouveau terminal, confirmez qu'il a été correctement installé avec :
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ deta --help
|
||||
|
||||
Deta command line interface for managing deta micros.
|
||||
Complete documentation available at https://docs.deta.sh
|
||||
|
||||
Usage:
|
||||
deta [flags]
|
||||
deta [command]
|
||||
|
||||
Available Commands:
|
||||
auth Change auth settings for a deta micro
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
!!! tip "Astuce"
|
||||
Si vous rencontrez des problèmes pour installer le CLI, consultez la <a href="https://docs.deta. sh/docs/micros/getting_started?ref=fastapi" class="external-link" target="_blank">documentation officielle de Deta (en anglais)</a>.
|
||||
|
||||
## Connexion avec le CLI
|
||||
|
||||
Maintenant, connectez-vous à Deta depuis le CLI avec :
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ deta login
|
||||
|
||||
Please, log in from the web page. Waiting..
|
||||
Logged in successfully.
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Cela ouvrira un navigateur web et permettra une authentification automatique.
|
||||
|
||||
## Déployer avec Deta
|
||||
|
||||
Ensuite, déployez votre application avec le CLI de Deta :
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ deta new
|
||||
|
||||
Successfully created a new micro
|
||||
|
||||
// Notice the "endpoint" 🔍
|
||||
|
||||
{
|
||||
"name": "fastapideta",
|
||||
"runtime": "python3.7",
|
||||
"endpoint": "https://qltnci.deta.dev",
|
||||
"visor": "enabled",
|
||||
"http_auth": "enabled"
|
||||
}
|
||||
|
||||
Adding dependencies...
|
||||
|
||||
|
||||
---> 100%
|
||||
|
||||
|
||||
Successfully installed fastapi-0.61.1 pydantic-1.7.2 starlette-0.13.6
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Vous verrez un message JSON similaire à :
|
||||
|
||||
```JSON hl_lines="4"
|
||||
{
|
||||
"name": "fastapideta",
|
||||
"runtime": "python3.7",
|
||||
"endpoint": "https://qltnci.deta.dev",
|
||||
"visor": "enabled",
|
||||
"http_auth": "enabled"
|
||||
}
|
||||
```
|
||||
|
||||
!!! tip "Astuce"
|
||||
Votre déploiement aura une URL `"endpoint"` différente.
|
||||
|
||||
## Vérifiez
|
||||
|
||||
Maintenant, dans votre navigateur ouvrez votre URL `endpoint`. Dans l'exemple ci-dessus, c'était
|
||||
`https://qltnci.deta.dev`, mais la vôtre sera différente.
|
||||
|
||||
Vous verrez la réponse JSON de votre application FastAPI :
|
||||
|
||||
```JSON
|
||||
{
|
||||
"Hello": "World"
|
||||
}
|
||||
```
|
||||
|
||||
Et maintenant naviguez vers `/docs` dans votre API, dans l'exemple ci-dessus ce serait `https://qltnci.deta.dev/docs`.
|
||||
|
||||
Vous verrez votre documentation comme suit :
|
||||
|
||||
<img src="/img/deployment/deta/image01.png">
|
||||
|
||||
## Activer l'accès public
|
||||
|
||||
Par défaut, Deta va gérer l'authentification en utilisant des cookies pour votre compte.
|
||||
|
||||
Mais une fois que vous êtes prêt, vous pouvez le rendre public avec :
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ deta auth disable
|
||||
|
||||
Successfully disabled http auth
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Maintenant, vous pouvez partager cette URL avec n'importe qui et ils seront en mesure d'accéder à votre API. 🚀
|
||||
|
||||
## HTTPS
|
||||
|
||||
Félicitations ! Vous avez déployé votre application FastAPI sur Deta ! 🎉 🍰
|
||||
|
||||
Remarquez également que Deta gère correctement HTTPS pour vous, vous n'avez donc pas à vous en occuper et pouvez être sûr que vos clients auront une connexion cryptée sécurisée. ✅ 🔒
|
||||
|
||||
## Vérifiez le Visor
|
||||
|
||||
À partir de l'interface graphique de votre documentation (dans une URL telle que `https://qltnci.deta.dev/docs`)
|
||||
envoyez une requête à votre *opération de chemin* `/items/{item_id}`.
|
||||
|
||||
Par exemple avec l'ID `5`.
|
||||
|
||||
Allez maintenant sur <a href="https://web.deta.sh/" class="external-link" target="_blank">https://web.deta.sh</a>.
|
||||
|
||||
Vous verrez qu'il y a une section à gauche appelée <abbr title="ça vient de Micro(server)">"Micros"</abbr> avec chacune de vos applications.
|
||||
|
||||
Vous verrez un onglet avec "Details", et aussi un onglet "Visor", allez à l'onglet "Visor".
|
||||
|
||||
Vous pouvez y consulter les requêtes récentes envoyées à votre application.
|
||||
|
||||
Vous pouvez également les modifier et les relancer.
|
||||
|
||||
<img src="/img/deployment/deta/image02.png">
|
||||
|
||||
## En savoir plus
|
||||
|
||||
À un moment donné, vous voudrez probablement stocker certaines données pour votre application d'une manière qui
|
||||
persiste dans le temps. Pour cela, vous pouvez utiliser <a href="https://docs.deta.sh/docs/base/py_tutorial?ref=fastapi" class="external-link" target="_blank">Deta Base</a>, il dispose également d'un généreux **plan gratuit**.
|
||||
|
||||
Vous pouvez également en lire plus dans la <a href="https://docs.deta.sh?ref=fastapi" class="external-link" target="_blank">documentation Deta</a>.
|
||||
53
docs/fr/docs/deployment/https.md
Normal file
53
docs/fr/docs/deployment/https.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# À propos de HTTPS
|
||||
|
||||
Il est facile de penser que HTTPS peut simplement être "activé" ou non.
|
||||
|
||||
Mais c'est beaucoup plus complexe que cela.
|
||||
|
||||
!!! tip
|
||||
Si vous êtes pressé ou si cela ne vous intéresse pas, passez aux sections suivantes pour obtenir des instructions étape par étape afin de tout configurer avec différentes techniques.
|
||||
|
||||
Pour apprendre les bases du HTTPS, du point de vue d'un utilisateur, consultez <a href="https://howhttps.works/"
|
||||
class="external-link" target="_blank">https://howhttps.works/</a>.
|
||||
|
||||
Maintenant, du point de vue d'un développeur, voici plusieurs choses à avoir en tête en pensant au HTTPS :
|
||||
|
||||
* Pour le HTTPS, le serveur a besoin de "certificats" générés par une tierce partie.
|
||||
* Ces certificats sont en fait acquis auprès de la tierce partie, et non "générés".
|
||||
* Les certificats ont une durée de vie.
|
||||
* Ils expirent.
|
||||
* Puis ils doivent être renouvelés et acquis à nouveau auprès de la tierce partie.
|
||||
* Le cryptage de la connexion se fait au niveau du protocole TCP.
|
||||
* C'est une couche en dessous de HTTP.
|
||||
* Donc, le certificat et le traitement du cryptage sont faits avant HTTP.
|
||||
* TCP ne connaît pas les "domaines", seulement les adresses IP.
|
||||
* L'information sur le domaine spécifique demandé se trouve dans les données HTTP.
|
||||
* Les certificats HTTPS "certifient" un certain domaine, mais le protocole et le cryptage se font au niveau TCP, avant de savoir quel domaine est traité.
|
||||
* Par défaut, cela signifie que vous ne pouvez avoir qu'un seul certificat HTTPS par adresse IP.
|
||||
* Quelle que soit la taille de votre serveur ou la taille de chacune des applications qu'il contient.
|
||||
* Il existe cependant une solution à ce problème.
|
||||
* Il existe une extension du protocole TLS (celui qui gère le cryptage au niveau TCP, avant HTTP) appelée <a
|
||||
href="https://fr.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr
|
||||
title="Server Name Indication (indication du nom du serveur)">SNI (indication du nom du serveur)</abbr></a>.
|
||||
* Cette extension SNI permet à un seul serveur (avec une seule adresse IP) d'avoir plusieurs certificats HTTPS et de servir plusieurs domaines/applications HTTPS.
|
||||
* Pour que cela fonctionne, un seul composant (programme) fonctionnant sur le serveur, écoutant sur l'adresse IP publique, doit avoir tous les certificats HTTPS du serveur.
|
||||
* Après avoir obtenu une connexion sécurisée, le protocole de communication est toujours HTTP.
|
||||
* Le contenu est crypté, même s'il est envoyé avec le protocole HTTP.
|
||||
|
||||
Il est courant d'avoir un seul programme/serveur HTTP fonctionnant sur le serveur (la machine, l'hôte, etc.) et
|
||||
gérant toutes les parties HTTPS : envoyer les requêtes HTTP décryptées à l'application HTTP réelle fonctionnant sur
|
||||
le même serveur (dans ce cas, l'application **FastAPI**), prendre la réponse HTTP de l'application, la crypter en utilisant le certificat approprié et la renvoyer au client en utilisant HTTPS. Ce serveur est souvent appelé un <a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">Proxy de terminaison TLS</a>.
|
||||
|
||||
## Let's Encrypt
|
||||
|
||||
Avant Let's Encrypt, ces certificats HTTPS étaient vendus par des tiers de confiance.
|
||||
|
||||
Le processus d'acquisition d'un de ces certificats était auparavant lourd, nécessitait pas mal de paperasses et les certificats étaient assez chers.
|
||||
|
||||
Mais ensuite, <a href="https://letsencrypt.org/" class="external-link" target="_blank">Let's Encrypt</a> a été créé.
|
||||
|
||||
Il s'agit d'un projet de la Fondation Linux. Il fournit des certificats HTTPS gratuitement. De manière automatisée. Ces certificats utilisent toutes les sécurités cryptographiques standard et ont une durée de vie courte (environ 3 mois), de sorte que la sécurité est en fait meilleure en raison de leur durée de vie réduite.
|
||||
|
||||
Les domaines sont vérifiés de manière sécurisée et les certificats sont générés automatiquement. Cela permet également d'automatiser le renouvellement de ces certificats.
|
||||
|
||||
L'idée est d'automatiser l'acquisition et le renouvellement de ces certificats, afin que vous puissiez disposer d'un HTTPS sécurisé, gratuitement et pour toujours.
|
||||
95
docs/fr/docs/deployment/versions.md
Normal file
95
docs/fr/docs/deployment/versions.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# À propos des versions de FastAPI
|
||||
|
||||
**FastAPI** est déjà utilisé en production dans de nombreuses applications et systèmes. Et la couverture de test est maintenue à 100 %. Mais son développement est toujours aussi rapide.
|
||||
|
||||
De nouvelles fonctionnalités sont ajoutées fréquemment, des bogues sont corrigés régulièrement et le code est
|
||||
amélioré continuellement.
|
||||
|
||||
C'est pourquoi les versions actuelles sont toujours `0.x.x`, cela reflète que chaque version peut potentiellement
|
||||
recevoir des changements non rétrocompatibles. Cela suit les conventions de <a href="https://semver.org/" class="external-link"
|
||||
target="_blank">versionnage sémantique</a>.
|
||||
|
||||
Vous pouvez créer des applications de production avec **FastAPI** dès maintenant (et vous le faites probablement depuis un certain temps), vous devez juste vous assurer que vous utilisez une version qui fonctionne correctement avec le reste de votre code.
|
||||
|
||||
## Épinglez votre version de `fastapi`
|
||||
|
||||
Tout d'abord il faut "épingler" la version de **FastAPI** que vous utilisez à la dernière version dont vous savez
|
||||
qu'elle fonctionne correctement pour votre application.
|
||||
|
||||
Par exemple, disons que vous utilisez la version `0.45.0` dans votre application.
|
||||
|
||||
Si vous utilisez un fichier `requirements.txt`, vous pouvez spécifier la version avec :
|
||||
|
||||
```txt
|
||||
fastapi==0.45.0
|
||||
```
|
||||
|
||||
ce qui signifierait que vous utiliseriez exactement la version `0.45.0`.
|
||||
|
||||
Ou vous pourriez aussi l'épingler avec :
|
||||
|
||||
```txt
|
||||
fastapi>=0.45.0,<0.46.0
|
||||
```
|
||||
|
||||
cela signifierait que vous utiliseriez les versions `0.45.0` ou supérieures, mais inférieures à `0.46.0`, par exemple, une version `0.45.2` serait toujours acceptée.
|
||||
|
||||
Si vous utilisez un autre outil pour gérer vos installations, comme Poetry, Pipenv, ou autres, ils ont tous un moyen que vous pouvez utiliser pour définir des versions spécifiques pour vos paquets.
|
||||
|
||||
## Versions disponibles
|
||||
|
||||
Vous pouvez consulter les versions disponibles (par exemple, pour vérifier quelle est la dernière version en date) dans les [Notes de version](../release-notes.md){.internal-link target=_blank}.
|
||||
|
||||
## À propos des versions
|
||||
|
||||
Suivant les conventions de versionnage sémantique, toute version inférieure à `1.0.0` peut potentiellement ajouter
|
||||
des changements non rétrocompatibles.
|
||||
|
||||
FastAPI suit également la convention que tout changement de version "PATCH" est pour des corrections de bogues et
|
||||
des changements rétrocompatibles.
|
||||
|
||||
!!! tip "Astuce"
|
||||
Le "PATCH" est le dernier chiffre, par exemple, dans `0.2.3`, la version PATCH est `3`.
|
||||
|
||||
Donc, vous devriez être capable d'épingler une version comme suit :
|
||||
|
||||
```txt
|
||||
fastapi>=0.45.0,<0.46.0
|
||||
```
|
||||
|
||||
Les changements non rétrocompatibles et les nouvelles fonctionnalités sont ajoutés dans les versions "MINOR".
|
||||
|
||||
!!! tip "Astuce"
|
||||
Le "MINOR" est le numéro au milieu, par exemple, dans `0.2.3`, la version MINOR est `2`.
|
||||
|
||||
## Mise à jour des versions FastAPI
|
||||
|
||||
Vous devriez tester votre application.
|
||||
|
||||
Avec **FastAPI** c'est très facile (merci à Starlette), consultez la documentation : [Testing](../tutorial/testing.md){.internal-link target=_blank}
|
||||
|
||||
Après avoir effectué des tests, vous pouvez mettre à jour la version **FastAPI** vers une version plus récente, et vous assurer que tout votre code fonctionne correctement en exécutant vos tests.
|
||||
|
||||
Si tout fonctionne, ou après avoir fait les changements nécessaires, et que tous vos tests passent, vous pouvez
|
||||
épingler votre version de `fastapi` à cette nouvelle version récente.
|
||||
|
||||
## À propos de Starlette
|
||||
|
||||
Vous ne devriez pas épingler la version de `starlette`.
|
||||
|
||||
Différentes versions de **FastAPI** utiliseront une version spécifique plus récente de Starlette.
|
||||
|
||||
Ainsi, vous pouvez simplement laisser **FastAPI** utiliser la bonne version de Starlette.
|
||||
|
||||
## À propos de Pydantic
|
||||
|
||||
Pydantic inclut des tests pour **FastAPI** avec ses propres tests, ainsi les nouvelles versions de Pydantic (au-dessus
|
||||
de `1.0.0`) sont toujours compatibles avec **FastAPI**.
|
||||
|
||||
Vous pouvez épingler Pydantic à toute version supérieure à `1.0.0` qui fonctionne pour vous et inférieure à `2.0.0`.
|
||||
|
||||
Par exemple :
|
||||
|
||||
```txt
|
||||
pydantic>=1.2.0,<2.0.0
|
||||
```
|
||||
122
docs/fr/docs/help-fastapi.md
Normal file
122
docs/fr/docs/help-fastapi.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# Help FastAPI - Obtenir de l'aide
|
||||
|
||||
Aimez-vous **FastAPI** ?
|
||||
|
||||
Vous souhaitez aider FastAPI, les autres utilisateurs et l'auteur ?
|
||||
|
||||
Ou souhaitez-vous obtenir de l'aide avec le **FastAPI** ?
|
||||
|
||||
Il existe des moyens très simples d'aider (plusieurs ne nécessitent qu'un ou deux clics).
|
||||
|
||||
Il existe également plusieurs façons d'obtenir de l'aide.
|
||||
|
||||
## Star **FastAPI** sur GitHub
|
||||
|
||||
Vous pouvez "star" FastAPI dans GitHub (en cliquant sur le bouton étoile en haut à droite) : <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>. ⭐️
|
||||
|
||||
En ajoutant une étoile, les autres utilisateurs pourront la trouver plus facilement et constater qu'elle a déjà été utile à d'autres.
|
||||
|
||||
## Watch le dépôt GitHub pour les releases
|
||||
|
||||
Vous pouvez "watch" FastAPI dans GitHub (en cliquant sur le bouton "watch" en haut à droite) : <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>. 👀
|
||||
|
||||
Vous pouvez y sélectionner "Releases only".
|
||||
|
||||
Ainsi, vous recevrez des notifications (dans votre courrier électronique) chaque fois qu'il y aura une nouvelle version de **FastAPI** avec des corrections de bugs et de nouvelles fonctionnalités.
|
||||
|
||||
## Se rapprocher de l'auteur
|
||||
|
||||
Vous pouvez vous rapprocher de <a href="https://tiangolo.com" class="external-link" target="_blank">moi (Sebastián Ramírez / `tiangolo`)</a>, l'auteur.
|
||||
|
||||
Vous pouvez :
|
||||
|
||||
* <a href="https://github.com/tiangolo" class="external-link" target="_blank">Me suivre sur **GitHub**</a>.
|
||||
* Voir d'autres projets Open Source que j'ai créés et qui pourraient vous aider.
|
||||
* Suivez-moi pour voir quand je crée un nouveau projet Open Source.
|
||||
* <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 🤷♂).
|
||||
* 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.
|
||||
|
||||
## Tweeter sur **FastAPI**
|
||||
|
||||
<a href="https://twitter.com/compose/tweet?text=I'm loving FastAPI because... https://github.com/tiangolo/fastapi cc @tiangolo" class="external-link" target="_blank">Tweetez à propos de **FastAPI**</a> et faites-moi savoir, ainsi qu'aux autres, pourquoi vous aimez ça. 🎉
|
||||
|
||||
J'aime entendre parler de l'utilisation du **FastAPI**, de ce que vous avez aimé dedans, dans quel projet/entreprise l'utilisez-vous, etc.
|
||||
|
||||
## Voter pour FastAPI
|
||||
|
||||
* <a href="https://www.slant.co/options/34241/~fastapi-review" class="external-link" target="_blank">Votez pour **FastAPI** sur Slant</a>.
|
||||
* <a href="https://alternativeto.net/software/fastapi/" class="external-link" target="_blank">Votez pour **FastAPI** sur AlternativeTo</a>.
|
||||
* <a href="https://github.com/marmelab/awesome-rest/pull/93" class="external-link" target="_blank">Votez pour **FastAPI** sur awesome-rest</a>.
|
||||
|
||||
## Aider les autres à résoudre les problèmes dans GitHub
|
||||
|
||||
Vous pouvez voir <a href="https://github.com/tiangolo/fastapi/issues" class="external-link" target="_blank">les problèmes existants</a> et essayer d'aider les autres, la plupart du temps il s'agit de questions dont vous connaissez peut-être déjà la réponse. 🤓
|
||||
|
||||
## Watch le dépôt GitHub
|
||||
|
||||
Vous pouvez "watch" FastAPI dans GitHub (en cliquant sur le bouton "watch" en haut à droite) : <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>. 👀
|
||||
|
||||
Si vous sélectionnez "Watching" au lieu de "Releases only", vous recevrez des notifications lorsque quelqu'un crée une nouvelle Issue.
|
||||
|
||||
Vous pouvez alors essayer de les aider à résoudre ces problèmes.
|
||||
|
||||
## Créer une Issue
|
||||
|
||||
Vous pouvez <a href="https://github.com/tiangolo/fastapi/issues/new/choose" class="external-link" target="_blank">créer une Issue</a> dans le dépôt GitHub, par exemple pour :
|
||||
|
||||
* Poser une question ou s'informer sur un problème.
|
||||
* Suggérer une nouvelle fonctionnalité.
|
||||
|
||||
**Note** : si vous créez un problème, alors je vais vous demander d'aider aussi les autres. 😉
|
||||
|
||||
## Créer une Pull Request
|
||||
|
||||
Vous pouvez <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">créer une Pull Request</a>, par exemple :
|
||||
|
||||
* Pour corriger une faute de frappe que vous avez trouvée sur la documentation.
|
||||
* Proposer de nouvelles sections de documentation.
|
||||
* Pour corriger une Issue/Bug existant.
|
||||
* Pour ajouter une nouvelle fonctionnalité.
|
||||
|
||||
## Rejoindre le chat
|
||||
|
||||
<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
|
||||
<img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Rejoindre le chat à https://gitter.im/tiangolo/fastapi">
|
||||
</a>
|
||||
|
||||
Rejoignez le chat sur Gitter: <a href="https://gitter.im/tiangolo/fastapi" class="external-link" target="_blank">https://gitter.im/tiangolo/fastapi</a>.
|
||||
|
||||
Vous pouvez y avoir des conversations rapides avec d'autres personnes, aider les autres, partager des idées, etc.
|
||||
|
||||
Mais gardez à l'esprit que, comme il permet une "conversation plus libre", il est facile de poser des questions trop générales et plus difficiles à répondre, de sorte que vous risquez de ne pas recevoir de réponses.
|
||||
|
||||
Dans les Issues de GitHub, le modèle vous guidera pour écrire la bonne question afin que vous puissiez plus facilement obtenir une bonne réponse, ou même résoudre le problème vous-même avant même de le poser. Et dans GitHub, je peux m'assurer que je réponds toujours à tout, même si cela prend du temps. Je ne peux pas faire cela personnellement avec le chat Gitter. 😅
|
||||
|
||||
Les conversations dans Gitter ne sont pas non plus aussi facilement consultables que dans GitHub, de sorte que les questions et les réponses peuvent se perdre dans la conversation.
|
||||
|
||||
De l'autre côté, il y a plus de 1000 personnes dans le chat, il y a donc de fortes chances que vous y trouviez quelqu'un à qui parler, presque tout le temps. 😄
|
||||
|
||||
## Parrainer l'auteur
|
||||
|
||||
Vous pouvez également soutenir financièrement l'auteur (moi) via <a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub sponsors</a>.
|
||||
|
||||
Là, vous pourriez m'offrir un café ☕️ pour me remercier 😄.
|
||||
|
||||
## Sponsoriser les outils qui font fonctionner FastAPI
|
||||
|
||||
Comme vous l'avez vu dans la documentation, FastAPI se tient sur les épaules des géants, Starlette et Pydantic.
|
||||
|
||||
Vous pouvez également parrainer :
|
||||
|
||||
* <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>
|
||||
|
||||
---
|
||||
|
||||
Merci ! 🚀
|
||||
@@ -111,7 +111,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
|
||||
|
||||
## Requirements
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI stands on the shoulders of giants:
|
||||
|
||||
|
||||
@@ -70,11 +70,15 @@ nav:
|
||||
- async.md
|
||||
- Déploiement:
|
||||
- deployment/index.md
|
||||
- deployment/versions.md
|
||||
- deployment/https.md
|
||||
- deployment/deta.md
|
||||
- deployment/docker.md
|
||||
- project-generation.md
|
||||
- alternatives.md
|
||||
- history-design-future.md
|
||||
- external-links.md
|
||||
- help-fastapi.md
|
||||
markdown_extensions:
|
||||
- toc:
|
||||
permalink: true
|
||||
|
||||
@@ -111,7 +111,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
|
||||
|
||||
## Requirements
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI stands on the shoulders of giants:
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
|
||||
|
||||
## Requirements
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI stands on the shoulders of giants:
|
||||
|
||||
|
||||
@@ -88,62 +88,29 @@ $ python -m venv env
|
||||
!!! tip "豆知識"
|
||||
この環境で`pip`を使って新しいパッケージをインストールするたびに、仮想環境を再度有効化します。
|
||||
|
||||
これにより、そのパッケージによってインストールされたターミナルのプログラム (`flit`など) を使用する場合、ローカル環境のものを使用し、グローバルにインストールされたものは使用されなくなります。
|
||||
これにより、そのパッケージによってインストールされたターミナルのプログラム を使用する場合、ローカル環境のものを使用し、グローバルにインストールされたものは使用されなくなります。
|
||||
|
||||
### Flit
|
||||
### pip
|
||||
|
||||
**FastAPI**は<a href="https://flit.readthedocs.io/en/latest/index.html" class="external-link" target="_blank">Flit</a> を使って、ビルド、パッケージ化、公開します。
|
||||
|
||||
上記のように環境を有効化した後、`flit`をインストールします:
|
||||
上記のように環境を有効化した後:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install flit
|
||||
$ pip install -e ."[dev,doc,test]"
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
次に、環境を再び有効化して、インストールしたばかりの`flit` (グローバルではない) を使用していることを確認します。
|
||||
|
||||
そして、`flit`を使用して開発のための依存関係をインストールします:
|
||||
|
||||
=== "Linux, macOS"
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ flit install --deps develop --symlink
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
=== "Windows"
|
||||
|
||||
Windowsユーザーは、`--symlink`のかわりに`--pth-file`を使用します:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ flit install --deps develop --pth-file
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
これで、すべての依存関係とFastAPIを、ローカル環境にインストールします。
|
||||
|
||||
#### ローカル環境でFastAPIを使う
|
||||
|
||||
FastAPIをインポートして使用するPythonファイルを作成し、ローカル環境で実行すると、ローカルのFastAPIソースコードが使用されます。
|
||||
|
||||
そして、`--symlink` (Windowsでは` --pth-file`) でインストールされているローカルのFastAPIソースコードを更新した場合、そのPythonファイルを再度実行すると、更新したばかりの新しいバージョンのFastAPIが使用されます。
|
||||
そして、`-e` でインストールされているローカルのFastAPIソースコードを更新した場合、そのPythonファイルを再度実行すると、更新したばかりの新しいバージョンのFastAPIが使用されます。
|
||||
|
||||
これにより、ローカルバージョンを「インストール」しなくても、すべての変更をテストできます。
|
||||
|
||||
@@ -161,7 +128,7 @@ $ bash scripts/format.sh
|
||||
|
||||
また、すべてのインポートを自動でソートします。
|
||||
|
||||
正しく並べ替えるには、上記セクションのコマンドで `--symlink` (Windowsの場合は` --pth-file`) を使い、FastAPIをローカル環境にインストールしている必要があります。
|
||||
正しく並べ替えるには、上記セクションのコマンドで `-e` を使い、FastAPIをローカル環境にインストールしている必要があります。
|
||||
|
||||
### インポートの整形
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ FastAPI は、Pythonの標準である型ヒントに基づいてPython 3.6 以
|
||||
|
||||
## 必要条件
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI は巨人の肩の上に立っています。
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트
|
||||
|
||||
## 요구사항
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI는 거인들의 어깨 위에 서 있습니다:
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
|
||||
|
||||
## Requirements
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI stands on the shoulders of giants:
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ Jeżeli tworzysz aplikacje <abbr title="aplikacja z interfejsem konsolowym">CLI<
|
||||
|
||||
## Wymagania
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI oparty jest na:
|
||||
|
||||
|
||||
@@ -89,61 +89,29 @@ Se ele exibir o binário `pip` em `env/bin/pip` então funcionou. 🎉
|
||||
!!! tip
|
||||
Toda vez que você instalar um novo pacote com `pip` nesse ambiente, ative o ambiente novamente.
|
||||
|
||||
Isso garante que se você usar um programa instalado por aquele pacote (como `flit`), você utilizará aquele de seu ambiente local e não outro que possa estar instalado globalmente.
|
||||
Isso garante que se você usar um programa instalado por aquele pacote, você utilizará aquele de seu ambiente local e não outro que possa estar instalado globalmente.
|
||||
|
||||
### Flit
|
||||
### pip
|
||||
|
||||
**FastAPI** utiliza <a href="https://flit.readthedocs.io/en/latest/index.html" class="external-link" target="_blank">Flit</a> para construir, empacotar e publicar o projeto.
|
||||
|
||||
Após ativar o ambiente como descrito acima, instale o `flit`:
|
||||
Após ativar o ambiente como descrito acima:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install flit
|
||||
$ pip install -e ."[dev,doc,test]"
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Ative novamente o ambiente para ter certeza que você esteja utilizando o `flit` que você acabou de instalar (e não um global).
|
||||
|
||||
E agora use `flit` para instalar as dependências de desenvolvimento:
|
||||
|
||||
=== "Linux, macOS"
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ flit install --deps develop --symlink
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
=== "Windows"
|
||||
|
||||
Se você está no Windows, use `--pth-file` ao invés de `--symlink`:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ flit install --deps develop --pth-file
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Isso irá instalar todas as dependências e seu FastAPI local em seu ambiente local.
|
||||
|
||||
#### Usando seu FastAPI local
|
||||
|
||||
Se você cria um arquivo Python que importa e usa FastAPI, e roda com Python de seu ambiente local, ele irá utilizar o código fonte de seu FastAPI local.
|
||||
|
||||
E se você atualizar o código fonte do FastAPI local, como ele é instalado com `--symlink` (ou `--pth-file` no Windows), quando você rodar aquele arquivo Python novamente, ele irá utilizar a nova versão do FastAPI que você acabou de editar.
|
||||
E se você atualizar o código fonte do FastAPI local, como ele é instalado com `-e`, quando você rodar aquele arquivo Python novamente, ele irá utilizar a nova versão do FastAPI que você acabou de editar.
|
||||
|
||||
Desse modo, você não tem que "instalar" sua versão local para ser capaz de testar cada mudança.
|
||||
|
||||
@@ -161,7 +129,7 @@ $ bash scripts/format.sh
|
||||
|
||||
Ele irá organizar também todos os seus imports.
|
||||
|
||||
Para que ele organize os imports corretamente, você precisa ter o FastAPI instalado localmente em seu ambiente, com o comando na seção acima usando `--symlink` (ou `--pth-file` no Windows).
|
||||
Para que ele organize os imports corretamente, você precisa ter o FastAPI instalado localmente em seu ambiente, com o comando na seção acima usando `-e`.
|
||||
|
||||
### Formato dos imports
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ Se você estiver construindo uma aplicação <abbr title="Command Line Interface
|
||||
|
||||
## Requisitos
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI está nos ombros de gigantes:
|
||||
|
||||
|
||||
213
docs/pt/docs/tutorial/body-multiple-params.md
Normal file
213
docs/pt/docs/tutorial/body-multiple-params.md
Normal file
@@ -0,0 +1,213 @@
|
||||
# Corpo - Múltiplos parâmetros
|
||||
|
||||
Agora que nós vimos como usar `Path` e `Query`, veremos usos mais avançados de declarações no corpo da requisição.
|
||||
|
||||
## Misture `Path`, `Query` e parâmetros de corpo
|
||||
|
||||
Primeiro, é claro, você pode misturar `Path`, `Query` e declarações de parâmetro no corpo da requisição livremente e o **FastAPI** saberá o que fazer.
|
||||
|
||||
E você também pode declarar parâmetros de corpo como opcionais, definindo o valor padrão com `None`:
|
||||
|
||||
=== "Python 3.6 e superiores"
|
||||
|
||||
```Python hl_lines="19-21"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 e superiores"
|
||||
|
||||
```Python hl_lines="17-19"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
!!! nota
|
||||
Repare que, neste caso, o `item` que seria capturado a partir do corpo é opcional. Visto que ele possui `None` como valor padrão.
|
||||
|
||||
## Múltiplos parâmetros de corpo
|
||||
|
||||
No exemplo anterior, as *operações de rota* esperariam um JSON no corpo contendo os atributos de um `Item`, exemplo:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"name": "Foo",
|
||||
"description": "The pretender",
|
||||
"price": 42.0,
|
||||
"tax": 3.2
|
||||
}
|
||||
```
|
||||
|
||||
Mas você pode também declarar múltiplos parâmetros de corpo, por exemplo, `item` e `user`:
|
||||
|
||||
=== "Python 3.6 e superiores"
|
||||
|
||||
```Python hl_lines="22"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial002.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 e superiores"
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
Neste caso, o **FastAPI** perceberá que existe mais de um parâmetro de corpo na função (dois parâmetros que são modelos Pydantic).
|
||||
|
||||
Então, ele usará o nome dos parâmetros como chaves (nome dos campos) no corpo, e espera um corpo como:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"description": "The pretender",
|
||||
"price": 42.0,
|
||||
"tax": 3.2
|
||||
},
|
||||
"user": {
|
||||
"username": "dave",
|
||||
"full_name": "Dave Grohl"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
!!! nota
|
||||
Repare que mesmo que o `item` esteja declarado da mesma maneira que antes, agora é esperado que ele esteja dentro do corpo com uma chave `item`.
|
||||
|
||||
|
||||
O **FastAPI** fará a conversão automática a partir da requisição, assim esse parâmetro `item` receberá seu respectivo conteúdo e o mesmo ocorrerá com `user`.
|
||||
|
||||
Ele executará a validação dos dados compostos e irá documentá-los de maneira compatível com o esquema OpenAPI e documentação automática.
|
||||
|
||||
## Valores singulares no corpo
|
||||
|
||||
Assim como existem uma `Query` e uma `Path` para definir dados adicionais para parâmetros de consulta e de rota, o **FastAPI** provê o equivalente para `Body`.
|
||||
|
||||
Por exemplo, extendendo o modelo anterior, você poder decidir por ter uma outra chave `importance` no mesmo corpo, além de `item` e `user`.
|
||||
|
||||
Se você declará-lo como é, porque é um valor singular, o **FastAPI** assumirá que se trata de um parâmetro de consulta.
|
||||
|
||||
Mas você pode instruir o **FastAPI** para tratá-lo como outra chave do corpo usando `Body`:
|
||||
|
||||
=== "Python 3.6 e superiores"
|
||||
|
||||
```Python hl_lines="22"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial003.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 e superiores"
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
Neste caso, o **FastAPI** esperará um corpo como:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"description": "The pretender",
|
||||
"price": 42.0,
|
||||
"tax": 3.2
|
||||
},
|
||||
"user": {
|
||||
"username": "dave",
|
||||
"full_name": "Dave Grohl"
|
||||
},
|
||||
"importance": 5
|
||||
}
|
||||
```
|
||||
|
||||
Mais uma vez, ele converterá os tipos de dados, validar, documentar, etc.
|
||||
|
||||
## Múltiplos parâmetros de corpo e consulta
|
||||
|
||||
Obviamente, você também pode declarar parâmetros de consulta assim que você precisar, de modo adicional a quaisquer parâmetros de corpo.
|
||||
|
||||
Dado que, por padrão, valores singulares são interpretados como parâmetros de consulta, você não precisa explicitamente adicionar uma `Query`, você pode somente:
|
||||
|
||||
```Python
|
||||
q: Union[str, None] = None
|
||||
```
|
||||
|
||||
Ou como em Python 3.10 e versões superiores:
|
||||
|
||||
```Python
|
||||
q: str | None = None
|
||||
```
|
||||
|
||||
Por exemplo:
|
||||
|
||||
=== "Python 3.6 e superiores"
|
||||
|
||||
```Python hl_lines="27"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial004.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 e superiores"
|
||||
|
||||
```Python hl_lines="26"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
!!! info "Informação"
|
||||
`Body` também possui todas as validações adicionais e metadados de parâmetros como em `Query`,`Path` e outras que você verá depois.
|
||||
|
||||
## Declare um único parâmetro de corpo indicando sua chave
|
||||
|
||||
Suponha que você tem um único parâmetro de corpo `item`, a partir de um modelo Pydantic `Item`.
|
||||
|
||||
Por padrão, o **FastAPI** esperará que seu conteúdo venha no corpo diretamente.
|
||||
|
||||
Mas se você quiser que ele espere por um JSON com uma chave `item` e dentro dele os conteúdos do modelo, como ocorre ao declarar vários parâmetros de corpo, você pode usar o parâmetro especial de `Body` chamado `embed`:
|
||||
|
||||
```Python
|
||||
item: Item = Body(embed=True)
|
||||
```
|
||||
|
||||
como em:
|
||||
|
||||
=== "Python 3.6 e superiores"
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 e superiores"
|
||||
|
||||
```Python hl_lines="15"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
Neste caso o **FastAPI** esperará um corpo como:
|
||||
|
||||
```JSON hl_lines="2"
|
||||
{
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"description": "The pretender",
|
||||
"price": 42.0,
|
||||
"tax": 3.2
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
ao invés de:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"name": "Foo",
|
||||
"description": "The pretender",
|
||||
"price": 42.0,
|
||||
"tax": 3.2
|
||||
}
|
||||
```
|
||||
|
||||
## Recapitulando
|
||||
|
||||
Você pode adicionar múltiplos parâmetros de corpo para sua *função de operação de rota*, mesmo que a requisição possa ter somente um único corpo.
|
||||
|
||||
E o **FastAPI** vai manipulá-los, mandar para você os dados corretos na sua função, e validar e documentar o schema correto na *operação de rota*.
|
||||
|
||||
Você também pode declarar valores singulares para serem recebidos como parte do corpo.
|
||||
|
||||
E você pode instruir o **FastAPI** para requisitar no corpo a indicação de chave mesmo quando existe somente um único parâmetro declarado.
|
||||
128
docs/pt/docs/tutorial/header-params.md
Normal file
128
docs/pt/docs/tutorial/header-params.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# Parâmetros de Cabeçalho
|
||||
|
||||
Você pode definir parâmetros de Cabeçalho da mesma maneira que define paramêtros com `Query`, `Path` e `Cookie`.
|
||||
|
||||
## importe `Header`
|
||||
|
||||
Primeiro importe `Header`:
|
||||
|
||||
=== "Python 3.6 and above"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/header_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 and above"
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
## Declare parâmetros de `Header`
|
||||
|
||||
Então declare os paramêtros de cabeçalho usando a mesma estrutura que em `Path`, `Query` e `Cookie`.
|
||||
|
||||
O primeiro valor é o valor padrão, você pode passar todas as validações adicionais ou parâmetros de anotação:
|
||||
|
||||
=== "Python 3.6 and above"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 and above"
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
!!! note "Detalhes Técnicos"
|
||||
`Header` é uma classe "irmã" de `Path`, `Query` e `Cookie`. Ela também herda da mesma classe em comum `Param`.
|
||||
|
||||
Mas lembre-se que quando você importa `Query`, `Path`, `Header`, e outras de `fastapi`, elas são na verdade funções que retornam classes especiais.
|
||||
|
||||
!!! info
|
||||
Para declarar headers, você precisa usar `Header`, caso contrário, os parâmetros seriam interpretados como parâmetros de consulta.
|
||||
|
||||
## Conversão automática
|
||||
|
||||
`Header` tem algumas funcionalidades a mais em relação a `Path`, `Query` e `Cookie`.
|
||||
|
||||
A maioria dos cabeçalhos padrão são separados pelo caractere "hífen", também conhecido como "sinal de menos" (`-`).
|
||||
|
||||
Mas uma variável como `user-agent` é inválida em Python.
|
||||
|
||||
Portanto, por padrão, `Header` converterá os caracteres de nomes de parâmetros de sublinhado (`_`) para hífen (`-`) para extrair e documentar os cabeçalhos.
|
||||
|
||||
Além disso, os cabeçalhos HTTP não diferenciam maiúsculas de minúsculas, portanto, você pode declará-los com o estilo padrão do Python (também conhecido como "snake_case").
|
||||
|
||||
Portanto, você pode usar `user_agent` como faria normalmente no código Python, em vez de precisar colocar as primeiras letras em maiúsculas como `User_Agent` ou algo semelhante.
|
||||
|
||||
Se por algum motivo você precisar desabilitar a conversão automática de sublinhados para hífens, defina o parâmetro `convert_underscores` de `Header` para `False`:
|
||||
|
||||
=== "Python 3.6 and above"
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/header_params/tutorial002.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 and above"
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/header_params/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
!!! warning "Aviso"
|
||||
Antes de definir `convert_underscores` como `False`, lembre-se de que alguns proxies e servidores HTTP não permitem o uso de cabeçalhos com sublinhados.
|
||||
|
||||
## Cabeçalhos duplicados
|
||||
|
||||
É possível receber cabeçalhos duplicados. Isso significa, o mesmo cabeçalho com vários valores.
|
||||
|
||||
Você pode definir esses casos usando uma lista na declaração de tipo.
|
||||
|
||||
Você receberá todos os valores do cabeçalho duplicado como uma `list` Python.
|
||||
|
||||
Por exemplo, para declarar um cabeçalho de `X-Token` que pode aparecer mais de uma vez, você pode escrever:
|
||||
|
||||
=== "Python 3.6 and above"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial003.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 and above"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial003_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 and above"
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/header_params/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
Se você se comunicar com essa *operação de caminho* enviando dois cabeçalhos HTTP como:
|
||||
|
||||
```
|
||||
X-Token: foo
|
||||
X-Token: bar
|
||||
```
|
||||
|
||||
A resposta seria como:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"X-Token values": [
|
||||
"bar",
|
||||
"foo"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Recapitulando
|
||||
|
||||
Declare cabeçalhos com `Header`, usando o mesmo padrão comum que utiliza-se em `Query`, `Path` e `Cookie`.
|
||||
|
||||
E não se preocupe com sublinhados em suas variáveis, FastAPI cuidará da conversão deles.
|
||||
138
docs/pt/docs/tutorial/path-params-numeric-validations.md
Normal file
138
docs/pt/docs/tutorial/path-params-numeric-validations.md
Normal file
@@ -0,0 +1,138 @@
|
||||
# Parâmetros da Rota e Validações Numéricas
|
||||
|
||||
Do mesmo modo que você pode declarar mais validações e metadados para parâmetros de consulta com `Query`, você pode declarar os mesmos tipos de validações e metadados para parâmetros de rota com `Path`.
|
||||
|
||||
## Importe `Path`
|
||||
|
||||
Primeiro, importe `Path` de `fastapi`:
|
||||
|
||||
=== "Python 3.6 e superiores"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 e superiores"
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
## Declare metadados
|
||||
|
||||
Você pode declarar todos os parâmetros da mesma maneira que na `Query`.
|
||||
|
||||
Por exemplo para declarar um valor de metadado `title` para o parâmetro de rota `item_id` você pode digitar:
|
||||
|
||||
=== "Python 3.6 e superiores"
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 e superiores"
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
!!! note "Nota"
|
||||
Um parâmetro de rota é sempre obrigatório, como se fizesse parte da rota.
|
||||
|
||||
Então, você deve declará-lo com `...` para marcá-lo como obrigatório.
|
||||
|
||||
Mesmo que você declare-o como `None` ou defina um valor padrão, isso não teria efeito algum, o parâmetro ainda seria obrigatório.
|
||||
|
||||
## Ordene os parâmetros de acordo com sua necessidade
|
||||
|
||||
Suponha que você queira declarar o parâmetro de consulta `q` como uma `str` obrigatória.
|
||||
|
||||
E você não precisa declarar mais nada em relação a este parâmetro, então você não precisa necessariamente usar `Query`.
|
||||
|
||||
Mas você ainda precisa usar `Path` para o parâmetro de rota `item_id`.
|
||||
|
||||
O Python irá acusar se você colocar um elemento com um valor padrão definido antes de outro que não tenha um valor padrão.
|
||||
|
||||
Mas você pode reordená-los, colocando primeiro o elemento sem o valor padrão (o parâmetro de consulta `q`).
|
||||
|
||||
Isso não faz diferença para o **FastAPI**. Ele vai detectar os parâmetros pelos seus nomes, tipos e definições padrão (`Query`, `Path`, etc), sem se importar com a ordem.
|
||||
|
||||
Então, você pode declarar sua função assim:
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/path_params_numeric_validations/tutorial002.py!}
|
||||
```
|
||||
|
||||
## Ordene os parâmetros de a acordo com sua necessidade, truques
|
||||
|
||||
Se você quiser declarar o parâmetro de consulta `q` sem um `Query` nem um valor padrão, e o parâmetro de rota `item_id` usando `Path`, e definí-los em uma ordem diferente, Python tem um pequeno truque na sintaxe para isso.
|
||||
|
||||
Passe `*`, como o primeiro parâmetro da função.
|
||||
|
||||
O Python não vai fazer nada com esse `*`, mas ele vai saber que a partir dali os parâmetros seguintes deverão ser chamados argumentos nomeados (pares chave-valor), também conhecidos como <abbr title="Do inglês: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>. Mesmo que eles não possuam um valor padrão.
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/path_params_numeric_validations/tutorial003.py!}
|
||||
```
|
||||
|
||||
## Validações numéricas: maior que ou igual
|
||||
|
||||
Com `Query` e `Path` (e outras que você verá mais tarde) você pode declarar restrições numéricas.
|
||||
|
||||
Aqui, com `ge=1`, `item_id` precisará ser um número inteiro maior que ("`g`reater than") ou igual ("`e`qual") a 1.
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!../../../docs_src/path_params_numeric_validations/tutorial004.py!}
|
||||
```
|
||||
|
||||
## Validações numéricas: maior que e menor que ou igual
|
||||
|
||||
O mesmo se aplica para:
|
||||
|
||||
* `gt`: maior que (`g`reater `t`han)
|
||||
* `le`: menor que ou igual (`l`ess than or `e`qual)
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../../docs_src/path_params_numeric_validations/tutorial005.py!}
|
||||
```
|
||||
|
||||
## Validações numéricas: valores do tipo float, maior que e menor que
|
||||
|
||||
Validações numéricas também funcionam para valores do tipo `float`.
|
||||
|
||||
Aqui é onde se torna importante a possibilidade de declarar <abbr title="greater than"><code>gt</code></abbr> e não apenas <abbr title="greater than or equal"><code>ge</code></abbr>. Com isso você pode especificar, por exemplo, que um valor deve ser maior que `0`, ainda que seja menor que `1`.
|
||||
|
||||
Assim, `0.5` seria um valor válido. Mas `0.0` ou `0` não seria.
|
||||
|
||||
E o mesmo para <abbr title="less than"><code>lt</code></abbr>.
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!../../../docs_src/path_params_numeric_validations/tutorial006.py!}
|
||||
```
|
||||
|
||||
## Recapitulando
|
||||
|
||||
Com `Query`, `Path` (e outras que você ainda não viu) você pode declarar metadados e validações de texto do mesmo modo que com [Parâmetros de consulta e validações de texto](query-params-str-validations.md){.internal-link target=_blank}.
|
||||
|
||||
E você também pode declarar validações numéricas:
|
||||
|
||||
* `gt`: maior que (`g`reater `t`han)
|
||||
* `ge`: maior que ou igual (`g`reater than or `e`qual)
|
||||
* `lt`: menor que (`l`ess `t`han)
|
||||
* `le`: menor que ou igual (`l`ess than or `e`qual)
|
||||
|
||||
!!! info "Informação"
|
||||
`Query`, `Path` e outras classes que você verá a frente são subclasses de uma classe comum `Param`.
|
||||
|
||||
Todas elas compartilham os mesmos parâmetros para validação adicional e metadados que você viu.
|
||||
|
||||
!!! note "Detalhes Técnicos"
|
||||
Quando você importa `Query`, `Path` e outras de `fastapi`, elas são na verdade funções.
|
||||
|
||||
Que quando chamadas, retornam instâncias de classes de mesmo nome.
|
||||
|
||||
Então, você importa `Query`, que é uma função. E quando você a chama, ela retorna uma instância de uma classe também chamada `Query`.
|
||||
|
||||
Estas funções são assim (ao invés de apenas usar as classes diretamente) para que seu editor não acuse erros sobre seus tipos.
|
||||
|
||||
Dessa maneira você pode user seu editor e ferramentas de desenvolvimento sem precisar adicionar configurações customizadas para ignorar estes erros.
|
||||
58
docs/pt/docs/tutorial/request-forms.md
Normal file
58
docs/pt/docs/tutorial/request-forms.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Dados do formulário
|
||||
|
||||
Quando você precisar receber campos de formulário ao invés de JSON, você pode usar `Form`.
|
||||
|
||||
!!! info "Informação"
|
||||
Para usar formulários, primeiro instale <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
|
||||
|
||||
Ex: `pip install python-multipart`.
|
||||
|
||||
## Importe `Form`
|
||||
|
||||
Importe `Form` de `fastapi`:
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/request_forms/tutorial001.py!}
|
||||
```
|
||||
|
||||
## Declare parâmetros de `Form`
|
||||
|
||||
Crie parâmetros de formulário da mesma forma que você faria para `Body` ou `Query`:
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/request_forms/tutorial001.py!}
|
||||
```
|
||||
|
||||
Por exemplo, em uma das maneiras que a especificação OAuth2 pode ser usada (chamada "fluxo de senha"), é necessário enviar um `username` e uma `password` como campos do formulário.
|
||||
|
||||
A <abbr title="especificação">spec</abbr> exige que os campos sejam exatamente nomeados como `username` e `password` e sejam enviados como campos de formulário, não JSON.
|
||||
|
||||
Com `Form` você pode declarar os mesmos metadados e validação que com `Body` (e `Query`, `Path`, `Cookie`).
|
||||
|
||||
!!! info "Informação"
|
||||
`Form` é uma classe que herda diretamente de `Body`.
|
||||
|
||||
!!! tip "Dica"
|
||||
Para declarar corpos de formulário, você precisa usar `Form` explicitamente, porque sem ele os parâmetros seriam interpretados como parâmetros de consulta ou parâmetros de corpo (JSON).
|
||||
|
||||
## Sobre "Campos de formulário"
|
||||
|
||||
A forma como os formulários HTML (`<form></form>`) enviam os dados para o servidor normalmente usa uma codificação "especial" para esses dados, é diferente do JSON.
|
||||
|
||||
O **FastAPI** fará a leitura desses dados no lugar certo em vez de JSON.
|
||||
|
||||
!!! note "Detalhes técnicos"
|
||||
Os dados dos formulários são normalmente codificados usando o "tipo de mídia" `application/x-www-form-urlencoded`.
|
||||
|
||||
Mas quando o formulário inclui arquivos, ele é codificado como `multipart/form-data`. Você lerá sobre como lidar com arquivos no próximo capítulo.
|
||||
|
||||
Se você quiser ler mais sobre essas codificações e campos de formulário, vá para o <a href="https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> web docs para <code>POST</code></a>.
|
||||
|
||||
!!! warning "Aviso"
|
||||
Você pode declarar vários parâmetros `Form` em uma *operação de caminho*, mas não pode declarar campos `Body` que espera receber como JSON, pois a solicitação terá o corpo codificado usando `application/x-www- form-urlencoded` em vez de `application/json`.
|
||||
|
||||
Esta não é uma limitação do **FastAPI**, é parte do protocolo HTTP.
|
||||
|
||||
## Recapitulando
|
||||
|
||||
Use `Form` para declarar os parâmetros de entrada de dados de formulário.
|
||||
91
docs/pt/docs/tutorial/response-status-code.md
Normal file
91
docs/pt/docs/tutorial/response-status-code.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Código de status de resposta
|
||||
|
||||
Da mesma forma que você pode especificar um modelo de resposta, você também pode declarar o código de status HTTP usado para a resposta com o parâmetro `status_code` em qualquer uma das *operações de caminho*:
|
||||
|
||||
* `@app.get()`
|
||||
* `@app.post()`
|
||||
* `@app.put()`
|
||||
* `@app.delete()`
|
||||
* etc.
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/response_status_code/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note "Nota"
|
||||
Observe que `status_code` é um parâmetro do método "decorador" (get, post, etc). Não da sua função de *operação de caminho*, como todos os parâmetros e corpo.
|
||||
|
||||
O parâmetro `status_code` recebe um número com o código de status HTTP.
|
||||
|
||||
!!! info "Informação"
|
||||
`status_code` também pode receber um `IntEnum`, como o do Python <a href="https://docs.python.org/3/library/http.html#http.HTTPStatus" class="external-link" target="_blank">`http.HTTPStatus`</a>.
|
||||
|
||||
Dessa forma:
|
||||
|
||||
* Este código de status será retornado na resposta.
|
||||
* Será documentado como tal no esquema OpenAPI (e, portanto, nas interfaces do usuário):
|
||||
|
||||
<img src="/img/tutorial/response-status-code/image01.png">
|
||||
|
||||
!!! note "Nota"
|
||||
Alguns códigos de resposta (consulte a próxima seção) indicam que a resposta não possui um corpo.
|
||||
|
||||
O FastAPI sabe disso e produzirá documentos OpenAPI informando que não há corpo de resposta.
|
||||
|
||||
## Sobre os códigos de status HTTP
|
||||
|
||||
!!! note "Nota"
|
||||
Se você já sabe o que são códigos de status HTTP, pule para a próxima seção.
|
||||
|
||||
Em HTTP, você envia um código de status numérico de 3 dígitos como parte da resposta.
|
||||
|
||||
Esses códigos de status têm um nome associado para reconhecê-los, mas o importante é o número.
|
||||
|
||||
Resumidamente:
|
||||
|
||||
|
||||
* `100` e acima são para "Informações". Você raramente os usa diretamente. As respostas com esses códigos de status não podem ter um corpo.
|
||||
* **`200`** e acima são para respostas "Bem-sucedidas". Estes são os que você mais usaria.
|
||||
* `200` é o código de status padrão, o que significa que tudo estava "OK".
|
||||
* Outro exemplo seria `201`, "Criado". É comumente usado após a criação de um novo registro no banco de dados.
|
||||
* Um caso especial é `204`, "Sem Conteúdo". Essa resposta é usada quando não há conteúdo para retornar ao cliente e, portanto, a resposta não deve ter um corpo.
|
||||
* **`300`** e acima são para "Redirecionamento". As respostas com esses códigos de status podem ou não ter um corpo, exceto `304`, "Não modificado", que não deve ter um.
|
||||
* **`400`** e acima são para respostas de "Erro do cliente". Este é o segundo tipo que você provavelmente mais usaria.
|
||||
* Um exemplo é `404`, para uma resposta "Não encontrado".
|
||||
* Para erros genéricos do cliente, você pode usar apenas `400`.
|
||||
* `500` e acima são para erros do servidor. Você quase nunca os usa diretamente. Quando algo der errado em alguma parte do código do seu aplicativo ou servidor, ele retornará automaticamente um desses códigos de status.
|
||||
|
||||
!!! tip "Dica"
|
||||
Para saber mais sobre cada código de status e qual código serve para quê, verifique o <a href="https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Status" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> documentação sobre códigos de status HTTP</a>.
|
||||
|
||||
## Atalho para lembrar os nomes
|
||||
|
||||
Vamos ver o exemplo anterior novamente:
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/response_status_code/tutorial001.py!}
|
||||
```
|
||||
|
||||
`201` é o código de status para "Criado".
|
||||
|
||||
Mas você não precisa memorizar o que cada um desses códigos significa.
|
||||
|
||||
Você pode usar as variáveis de conveniência de `fastapi.status`.
|
||||
|
||||
```Python hl_lines="1 6"
|
||||
{!../../../docs_src/response_status_code/tutorial002.py!}
|
||||
```
|
||||
|
||||
Eles são apenas uma conveniência, eles possuem o mesmo número, mas dessa forma você pode usar o autocomplete do editor para encontrá-los:
|
||||
|
||||
<img src="/img/tutorial/response-status-code/image02.png">
|
||||
|
||||
!!! note "Detalhes técnicos"
|
||||
Você também pode usar `from starlette import status`.
|
||||
|
||||
**FastAPI** fornece o mesmo `starlette.status` como `fastapi.status` apenas como uma conveniência para você, o desenvolvedor. Mas vem diretamente da Starlette.
|
||||
|
||||
|
||||
## Alterando o padrão
|
||||
|
||||
Mais tarde, no [Guia do usuário avançado](../advanced/response-change-status-code.md){.internal-link target=_blank}, você verá como retornar um código de status diferente do padrão que você está declarando aqui.
|
||||
@@ -66,13 +66,19 @@ nav:
|
||||
- tutorial/path-params.md
|
||||
- tutorial/query-params.md
|
||||
- tutorial/body.md
|
||||
- tutorial/body-multiple-params.md
|
||||
- tutorial/body-fields.md
|
||||
- tutorial/extra-data-types.md
|
||||
- tutorial/query-params-str-validations.md
|
||||
- tutorial/path-params-numeric-validations.md
|
||||
- tutorial/cookie-params.md
|
||||
- tutorial/header-params.md
|
||||
- tutorial/response-status-code.md
|
||||
- tutorial/request-forms.md
|
||||
- tutorial/handling-errors.md
|
||||
- Segurança:
|
||||
- tutorial/security/index.md
|
||||
- tutorial/background-tasks.md
|
||||
- Guia de Usuário Avançado:
|
||||
- advanced/index.md
|
||||
- Implantação:
|
||||
|
||||
21
docs/ru/docs/deployment/index.md
Normal file
21
docs/ru/docs/deployment/index.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Развёртывание - Введение
|
||||
|
||||
Развернуть приложение **FastAPI** довольно просто.
|
||||
|
||||
## Да что такое это ваше - "развёртывание"?!
|
||||
|
||||
Термин **развёртывание** (приложения) означает выполнение необходимых шагов, чтобы сделать приложение **доступным для пользователей**.
|
||||
|
||||
Обычно **веб-приложения** размещают на удалённом компьютере с серверной программой, которая обеспечивает хорошую производительность, стабильность и т. д., Чтобы ваши пользователи могли эффективно, беспрерывно и беспроблемно обращаться к приложению.
|
||||
|
||||
Это отличется от **разработки**, когда вы постоянно меняете код, делаете в нём намеренные ошибки и исправляете их, останавливаете и перезапускаете сервер разработки и т. д.
|
||||
|
||||
## Стратегии развёртывания
|
||||
|
||||
В зависимости от вашего конкретного случая, есть несколько способов сделать это.
|
||||
|
||||
Вы можете **развернуть сервер** самостоятельно, используя различные инструменты. Например, можно использовать **облачный сервис**, который выполнит часть работы за вас. Также возможны и другие варианты.
|
||||
|
||||
В этом блоке я покажу вам некоторые из основных концепций, которые вы, вероятно, должны иметь в виду при развертывании приложения **FastAPI** (хотя большинство из них применимо к любому другому типу веб-приложений).
|
||||
|
||||
В последующих разделах вы узнаете больше деталей и методов, необходимых для этого. ✨
|
||||
87
docs/ru/docs/deployment/versions.md
Normal file
87
docs/ru/docs/deployment/versions.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# О версиях FastAPI
|
||||
|
||||
**FastAPI** уже используется в продакшене во многих приложениях и системах. Покрытие тестами поддерживается на уровне 100%. Однако его разработка все еще продолжается.
|
||||
|
||||
Часто добавляются новые функции, регулярно исправляются баги, код продолжает постоянно совершенствоваться.
|
||||
|
||||
По указанным причинам текущие версии до сих пор `0.x.x`. Это говорит о том, что каждая версия может содержать обратно несовместимые изменения, следуя <a href="https://semver.org/" class="external-link" target="_blank">соглашению о Семантическом Версионировании</a>.
|
||||
|
||||
Уже сейчас вы можете создавать приложения в продакшене, используя **FastAPI** (и скорее всего так и делаете), главное убедиться в том, что вы используете версию, которая корректно работает с вашим кодом.
|
||||
|
||||
## Закрепите вашу версию `fastapi`
|
||||
|
||||
Первым делом вам следует "закрепить" конкретную последнюю используемую версию **FastAPI**, которая корректно работает с вашим приложением.
|
||||
|
||||
Например, в своём приложении вы используете версию `0.45.0`.
|
||||
|
||||
Если вы используете файл `requirements.txt`, вы можете указать версию следующим способом:
|
||||
|
||||
```txt
|
||||
fastapi==0.45.0
|
||||
```
|
||||
|
||||
это означает, что вы будете использовать именно версию `0.45.0`.
|
||||
|
||||
Или вы можете закрепить версию следующим способом:
|
||||
|
||||
```txt
|
||||
fastapi>=0.45.0,<0.46.0
|
||||
```
|
||||
|
||||
это значит, что вы используете версии `0.45.0` или выше, но меньше чем `0.46.0`. Например, версия `0.45.2` все еще будет подходить.
|
||||
|
||||
Если вы используете любой другой инструмент для управления зависимостями, например Poetry, Pipenv или др., у них у всех имеется способ определения специфической версии для ваших пакетов.
|
||||
|
||||
## Доступные версии
|
||||
|
||||
Вы можете посмотреть доступные версии (например, проверить последнюю на данный момент) в [примечаниях к выпуску](../release-notes.md){.internal-link target=_blank}.
|
||||
|
||||
## О версиях
|
||||
|
||||
Следуя соглашению о Семантическом Версионировании, любые версии ниже `1.0.0` потенциально могут добавить обратно несовместимые изменения.
|
||||
|
||||
FastAPI следует соглашению в том, что любые изменения "ПАТЧ"-версии предназначены для исправления багов и внесения обратно совместимых изменений.
|
||||
|
||||
!!! Подсказка
|
||||
"ПАТЧ" - это последнее число. Например, в `0.2.3`, ПАТЧ-версия - это `3`.
|
||||
|
||||
Итак, вы можете закрепить версию следующим образом:
|
||||
|
||||
```txt
|
||||
fastapi>=0.45.0,<0.46.0
|
||||
```
|
||||
|
||||
Обратно несовместимые изменения и новые функции добавляются в "МИНОРНЫЕ" версии.
|
||||
|
||||
!!! Подсказка
|
||||
"МИНОРНАЯ" версия - это число в середине. Например, в `0.2.3` МИНОРНАЯ версия - это `2`.
|
||||
|
||||
## Обновление версий FastAPI
|
||||
|
||||
Вам следует добавить тесты для вашего приложения.
|
||||
|
||||
С помощью **FastAPI** это очень просто (благодаря Starlette), см. документацию: [Тестирование](../tutorial/testing.md){.internal-link target=_blank}
|
||||
|
||||
После создания тестов вы можете обновить свою версию **FastAPI** до более новой. После этого следует убедиться, что ваш код работает корректно, запустив тесты.
|
||||
|
||||
Если все работает корректно, или после внесения необходимых изменений все ваши тесты проходят, только тогда вы можете закрепить вашу новую версию `fastapi`.
|
||||
|
||||
## О Starlette
|
||||
|
||||
Не следует закреплять версию `starlette`.
|
||||
|
||||
Разные версии **FastAPI** будут использовать более новые версии Starlette.
|
||||
|
||||
Так что решение об используемой версии Starlette, вы можете оставить **FastAPI**.
|
||||
|
||||
## О Pydantic
|
||||
|
||||
Pydantic включает свои собственные тесты для **FastAPI**, так что новые версии Pydantic (выше `1.0.0`) всегда совместимы с FastAPI.
|
||||
|
||||
Вы можете закрепить любую версию Pydantic, которая вам подходит, выше `1.0.0` и ниже `2.0.0`.
|
||||
|
||||
Например:
|
||||
|
||||
```txt
|
||||
pydantic>=1.2.0,<2.0.0
|
||||
```
|
||||
203
docs/ru/docs/features.md
Normal file
203
docs/ru/docs/features.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# Основные свойства
|
||||
|
||||
## Основные свойства FastAPI
|
||||
|
||||
**FastAPI** предлагает вам следующее:
|
||||
|
||||
### Использование открытых стандартов
|
||||
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> для создания API, включая объявления <abbr title="также известных, как HTTP-методы, такие, как: POST, GET, PUT, DELETE">операций</abbr> <abbr title="известные как: эндпоинты, маршруты, 'ручки' и т.п.">пути</abbr>, параметров, тела запроса, безопасности и т.д.
|
||||
|
||||
|
||||
* Автоматическое документирование моделей данных в соответствии с <a href="https://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (так как спецификация OpenAPI сама основана на JSON Schema).
|
||||
* Разработан, придерживаясь этих стандартов, после тщательного их изучения. Эти стандарты изначально включены во фреймфорк, а не являются дополнительной надстройкой.
|
||||
* Это также позволяет использовать автоматическую **генерацию клиентского кода** на многих языках.
|
||||
|
||||
### Автоматически генерируемая документация
|
||||
|
||||
Интерактивная документация для API и исследования пользовательских веб-интерфейсов. Поскольку этот фреймворк основан на OpenAPI, существует несколько вариантов документирования, 2 из которых включены по умолчанию.
|
||||
|
||||
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank"><strong>Swagger UI</strong></a>, с интерактивным взаимодействием, вызывает и тестирует ваш API прямо из браузера.
|
||||
|
||||

|
||||
|
||||
* Альтернативная документация API в <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank"><strong>ReDoc</strong></a>.
|
||||
|
||||

|
||||
|
||||
### Только современный Python
|
||||
|
||||
Все эти возможности основаны на стандартных **аннотациях типов Python 3.6** (благодаря Pydantic). Не нужно изучать новый синтаксис. Только лишь стандартный современный Python.
|
||||
|
||||
Если вам нужно освежить знания, как использовать аннотации типов в Python (даже если вы не используете FastAPI), выделите 2 минуты и просмотрите краткое руководство: [Введение в аннотации типов Python¶
|
||||
](python-types.md){.internal-link target=_blank}.
|
||||
|
||||
Вы пишете на стандартном Python с аннотациями типов:
|
||||
|
||||
```Python
|
||||
from datetime import date
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
# Объявляем параметр user_id с типом `str`
|
||||
# и получаем поддержку редактора внутри функции
|
||||
def main(user_id: str):
|
||||
return user_id
|
||||
|
||||
|
||||
# Модель Pydantic
|
||||
class User(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
joined: date
|
||||
```
|
||||
|
||||
Это можно использовать так:
|
||||
|
||||
```Python
|
||||
my_user: User = User(id=3, name="John Doe", joined="2018-07-19")
|
||||
|
||||
second_user_data = {
|
||||
"id": 4,
|
||||
"name": "Mary",
|
||||
"joined": "2018-11-30",
|
||||
}
|
||||
|
||||
my_second_user: User = User(**second_user_data)
|
||||
```
|
||||
|
||||
!!! Информация
|
||||
`**second_user_data` означает:
|
||||
|
||||
Передать ключи и значения словаря `second_user_data`, в качестве аргументов типа "ключ-значение", это эквивалентно: `User(id=4, name="Mary", joined="2018-11-30")` .
|
||||
|
||||
### Поддержка редакторов (IDE)
|
||||
|
||||
Весь фреймворк был продуман так, чтобы быть простым и интуитивно понятным в использовании, все решения были проверены на множестве редакторов еще до начала разработки, чтобы обеспечить наилучшие условия при написании кода.
|
||||
|
||||
В опросе Python-разработчиков было выяснено, <a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" class="external-link" target="_blank">что наиболее часто используемой функцией редакторов, является "автодополнение"</a>.
|
||||
|
||||
Вся структура **FastAPI** основана на удовлетворении этой возможности. Автодополнение работает везде.
|
||||
|
||||
Вам редко нужно будет возвращаться к документации.
|
||||
|
||||
Вот как ваш редактор может вам помочь:
|
||||
|
||||
* в <a href="https://code.visualstudio.com/" class="external-link" target="_blank">Visual Studio Code</a>:
|
||||
|
||||

|
||||
|
||||
* в <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a>:
|
||||
|
||||

|
||||
|
||||
Вы будете получать автодополнение кода даже там, где вы считали это невозможным раньше.
|
||||
Как пример, ключ `price` внутри тела JSON (который может быть вложенным), приходящего в запросе.
|
||||
|
||||
Больше никаких неправильных имён ключей, метания по документации или прокручивания кода вверх и вниз, в попытках узнать - использовали вы ранее `username` или `user_name`.
|
||||
|
||||
### Краткость
|
||||
FastAPI имеет продуманные значения **по умолчанию** для всего, с произвольными настройками везде. Все параметры могут быть тонко подстроены так, чтобы делать то, что вам нужно и определять необходимый вам API.
|
||||
|
||||
Но, по умолчанию, всё это **"и так работает"**.
|
||||
|
||||
### Проверка значений
|
||||
|
||||
* Проверка значений для большинства (или всех?) **типов данных** Python, включая:
|
||||
* Объекты JSON (`dict`).
|
||||
* Массивы JSON (`list`) с установленными типами элементов.
|
||||
* Строковые (`str`) поля с ограничением минимальной и максимальной длины.
|
||||
* Числа (`int`, `float`) с минимальными и максимальными значениями и т.п.
|
||||
|
||||
* Проверка для более экзотических типов, таких как:
|
||||
* URL.
|
||||
* Email.
|
||||
* UUID.
|
||||
* ...и другие.
|
||||
|
||||
Все проверки обрабатываются хорошо зарекомендовавшим себя и надежным **Pydantic**.
|
||||
|
||||
### Безопасность и аутентификация
|
||||
|
||||
Встроеные функции безопасности и аутентификации. Без каких-либо компромиссов с базами данных или моделями данных.
|
||||
|
||||
Все схемы безопасности, определённые в OpenAPI, включая:
|
||||
|
||||
* HTTP Basic.
|
||||
* **OAuth2** (также с **токенами JWT**). Ознакомьтесь с руководством [OAuth2 с JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
|
||||
* Ключи API в:
|
||||
* Заголовках.
|
||||
* Параметрах запросов.
|
||||
* Cookies и т.п.
|
||||
|
||||
Вдобавок все функции безопасности от Starlette (включая **сессионные cookies**).
|
||||
|
||||
Все инструменты и компоненты спроектированы для многократного использования и легко интегрируются с вашими системами, хранилищами данных, реляционными и NoSQL базами данных и т. д.
|
||||
|
||||
### Внедрение зависимостей
|
||||
|
||||
FastAPI включает в себя чрезвычайно простую в использовании, но чрезвычайно мощную систему <abbr title='известную как: "components", "resources", "services", "providers"'><strong>Внедрения зависимостей</strong></abbr>.
|
||||
|
||||
* Даже зависимости могут иметь зависимости, создавая иерархию или **"графы" зависимостей**.
|
||||
* Всё **автоматически обрабатывается** фреймворком.
|
||||
* Все зависимости могут запрашивать данные из запросов и **дополнять операции пути** ограничениями и автоматической документацией.
|
||||
* **Автоматическая проверка** даже для параметров *операций пути*, определенных в зависимостях.
|
||||
* Поддержка сложных систем аутентификации пользователей, **соединений с базами данных** и т.д.
|
||||
* **Никаких компромиссов** с базами данных, интерфейсами и т.д. Но легкая интеграция со всеми ними.
|
||||
|
||||
### Нет ограничений на "Плагины"
|
||||
|
||||
Или, другими словами, нет сложностей с ними, импортируйте и используйте нужный вам код.
|
||||
|
||||
Любая интеграция разработана настолько простой в использовании (с зависимостями), что вы можете создать "плагин" для своего приложения в пару строк кода, используя ту же структуру и синтаксис, что и для ваших *операций пути*.
|
||||
|
||||
### Проверен
|
||||
|
||||
* 100% <abbr title="Количество автоматически проверямого кода">покрытие тестами</abbr>.
|
||||
* 100% <abbr title="Аннотации типов Python, благодаря которым ваш редактор и другие инструменты могут обеспечить вам лучшую поддержку">аннотирование типов</abbr> в кодовой базе.
|
||||
* Используется в реально работающих приложениях.
|
||||
|
||||
## Основные свойства Starlette
|
||||
|
||||
**FastAPI** основан на <a href="https://www.starlette.io/" class="external-link" target="_blank"><strong>Starlette</strong></a> и полностью совместим с ним. Так что, любой дополнительный код Starlette, который у вас есть, будет также работать.
|
||||
|
||||
На самом деле, `FastAPI` - это класс, унаследованный от `Starlette`. Таким образом, если вы уже знаете или используете Starlette, большая часть функционала будет работать так же.
|
||||
|
||||
С **FastAPI** вы получаете все возможности **Starlette** (так как FastAPI это всего лишь Starlette на стероидах):
|
||||
|
||||
* Серьёзно впечатляющая производительность. Это <a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank">один из самых быстрых фреймворков на Python</a>, наравне с приложениями использующими **NodeJS** или **Go**.
|
||||
* Поддержка **WebSocket**.
|
||||
* Фоновые задачи для процессов.
|
||||
* События запуска и выключения.
|
||||
* Тестовый клиент построен на библиотеке `requests`.
|
||||
* **CORS**, GZip, статические файлы, потоковые ответы.
|
||||
* Поддержка **сессий и cookie**.
|
||||
* 100% покрытие тестами.
|
||||
* 100% аннотирование типов в кодовой базе.
|
||||
|
||||
## Особенности и возможности Pydantic
|
||||
|
||||
**FastAPI** основан на <a href="https://pydantic-docs.helpmanual.io" class="external-link" target="_blank"><strong>Pydantic</strong></a> и полностью совместим с ним. Так что, любой дополнительный код Pydantic, который у вас есть, будет также работать.
|
||||
|
||||
Включая внешние библиотеки, также основанные на Pydantic, такие как: <abbr title="Object-Relational Mapper">ORM'ы</abbr>, <abbr title="Object-Document Mapper">ODM'ы</abbr> для баз данных.
|
||||
|
||||
Это также означает, что во многих случаях вы можете передавать тот же объект, который получили из запроса, **непосредственно в базу данных**, так как всё проверяется автоматически.
|
||||
|
||||
И наоборот, во многих случаях вы можете просто передать объект, полученный из базы данных, **непосредственно клиенту**.
|
||||
|
||||
С **FastAPI** вы получаете все возможности **Pydantic** (так как, FastAPI основан на Pydantic, для обработки данных):
|
||||
|
||||
* **Никакой нервотрёпки** :
|
||||
* Не нужно изучать новых схем в микроязыках.
|
||||
* Если вы знаете аннотации типов в Python, вы знаете, как использовать Pydantic.
|
||||
* Прекрасно сочетается с вашими **<abbr title="Интегрированное окружение для разработки, похожее на текстовый редактор">IDE</abbr>/<abbr title="программа проверяющая ошибки в коде">linter</abbr>/мозгом**:
|
||||
* Потому что структуры данных pydantic - это всего лишь экземпляры классов, определённых вами. Автодополнение, проверка кода, mypy и ваша интуиция - всё будет работать с вашими проверенными данными.
|
||||
* **Быстродействие**:
|
||||
* В <a href="https://pydantic-docs.helpmanual.io/benchmarks/" class="external-link" target="_blank">тестовых замерах</a> Pydantic быстрее, чем все другие проверенные библиотеки.
|
||||
* Проверка **сложных структур**:
|
||||
* Использование иерархических моделей Pydantic; `List`, `Dict` и т.п. из модуля `typing` (входит в стандартную библиотеку Python).
|
||||
* Валидаторы позволяют четко и легко определять, проверять и документировать сложные схемы данных в виде JSON Schema.
|
||||
* У вас могут быть глубоко **вложенные объекты JSON** и все они будут проверены и аннотированы.
|
||||
* **Расширяемость**:
|
||||
* Pydantic позволяет определять пользовательские типы данных или расширять проверку методами модели, с помощью проверочных декораторов.
|
||||
* 100% покрытие тестами.
|
||||
@@ -1,50 +1,48 @@
|
||||
|
||||
{!../../../docs/missing-translation.md!}
|
||||
|
||||
|
||||
<p align="center">
|
||||
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<em>FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
|
||||
<em>Готовый к внедрению высокопроизводительный фреймворк, простой в изучении и разработке.</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.com/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://travis-ci.com/tiangolo/fastapi.svg?branch=master" alt="Build Status">
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg?event=push&branch=master" alt="Test">
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi" alt="Coverage">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://badge.fury.io/py/fastapi.svg" alt="Package version">
|
||||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
**Documentation**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
|
||||
**Документация**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
|
||||
|
||||
**Source Code**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
|
||||
**Исходный код**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
|
||||
|
||||
---
|
||||
|
||||
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
|
||||
FastAPI — это современный, быстрый (высокопроизводительный) веб-фреймворк для создания API используя Python 3.6+, в основе которого лежит стандартная аннотация типов Python.
|
||||
|
||||
The key features are:
|
||||
Ключевые особенности:
|
||||
|
||||
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance).
|
||||
* **Скорость**: Очень высокая производительность, на уровне **NodeJS** и **Go** (благодаря Starlette и Pydantic). [Один из самых быстрых фреймворков Python](#_10).
|
||||
* **Быстрота разработки**: Увеличьте скорость разработки примерно на 200–300%. *
|
||||
* **Меньше ошибок**: Сократите примерно на 40% количество ошибок, вызванных человеком (разработчиком). *
|
||||
* **Интуитивно понятный**: Отличная поддержка редактора. <abbr title="также известное как автозаполнение, автодополнение, IntelliSense">Автозавершение</abbr> везде. Меньше времени на отладку.
|
||||
* **Лёгкость**: Разработан так, чтобы его было легко использовать и осваивать. Меньше времени на чтение документации.
|
||||
* **Краткость**: Сведите к минимуму дублирование кода. Каждый объявленный параметр - определяет несколько функций. Меньше ошибок.
|
||||
* **Надежность**: Получите готовый к работе код. С автоматической интерактивной документацией.
|
||||
* **На основе стандартов**: Основан на открытых стандартах API и полностью совместим с ними: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (ранее известном как Swagger) и <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
|
||||
* **Fast to code**: Increase the speed to develop features by about 200% to 300%. *
|
||||
* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. *
|
||||
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
|
||||
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
|
||||
* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
|
||||
* **Robust**: Get production-ready code. With automatic interactive documentation.
|
||||
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
<small>* оценка на основе тестов внутренней команды разработчиков, создающих производственные приложения.</small>
|
||||
|
||||
<small>* estimation based on tests on an internal development team, building production applications.</small>
|
||||
|
||||
## Sponsors
|
||||
## Спонсоры
|
||||
|
||||
<!-- sponsors -->
|
||||
|
||||
@@ -59,66 +57,66 @@ The key features are:
|
||||
|
||||
<!-- /sponsors -->
|
||||
|
||||
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a>
|
||||
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Другие спонсоры</a>
|
||||
|
||||
## Opinions
|
||||
## Отзывы
|
||||
|
||||
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
|
||||
"_В последнее время я много где использую **FastAPI**. [...] На самом деле я планирую использовать его для всех **сервисов машинного обучения моей команды в Microsoft**. Некоторые из них интегрируются в основной продукт **Windows**, а некоторые — в продукты **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>
|
||||
|
||||
---
|
||||
|
||||
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
|
||||
"_Мы использовали библиотеку **FastAPI** для создания сервера **REST**, к которому можно делать запросы для получения **прогнозов**. [для Ludwig]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
|
||||
"_**Netflix** рада объявить о выпуске опенсорсного фреймворка для оркестровки **антикризисного управления**: **Dispatch**! [создана с помощью **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>
|
||||
|
||||
---
|
||||
|
||||
"_I’m over the moon excited about **FastAPI**. It’s so fun!_"
|
||||
"_Я в полном восторге от **FastAPI**. Это так весело!_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
"_Честно говоря, то, что вы создали, выглядит очень солидно и отполировано. Во многих смыслах я хотел, чтобы **Hug** был именно таким — это действительно вдохновляет, когда кто-то создаёт такое._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
|
||||
"_Если вы хотите изучить какой-нибудь **современный фреймворк** для создания REST API, ознакомьтесь с **FastAPI** [...] Он быстрый, лёгкий и простой в изучении [...]_"
|
||||
|
||||
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
|
||||
"_Мы перешли на **FastAPI** для наших **API** [...] Я думаю, вам тоже понравится [...]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**, the FastAPI of CLIs
|
||||
## **Typer**, интерфейс командной строки для FastAPI
|
||||
|
||||
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
||||
|
||||
If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be used in the terminal instead of a web API, check out <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
|
||||
Если вы создаете приложение <abbr title="Интерфейс командной строки">CLI</abbr> для использования в терминале вместо веб-API, ознакомьтесь с <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
|
||||
|
||||
**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀
|
||||
**Typer** — младший брат FastAPI. И он предназначен для использования в качестве **интерфейса командной строки для FastAPI**. ⌨️ 🚀
|
||||
|
||||
## Requirements
|
||||
## Зависимости
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI stands on the shoulders of giants:
|
||||
FastAPI стоит на плечах гигантов:
|
||||
|
||||
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> for the web parts.
|
||||
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> for the data parts.
|
||||
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> для части связанной с вебом.
|
||||
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> для части связанной с данными.
|
||||
|
||||
## Installation
|
||||
## Установка
|
||||
|
||||
<div class="termy">
|
||||
|
||||
@@ -130,7 +128,7 @@ $ pip install fastapi
|
||||
|
||||
</div>
|
||||
|
||||
You will also need an ASGI server, for production such as <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
Вам также понадобится сервер ASGI для производства, такой как <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> или <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
@@ -142,11 +140,11 @@ $ pip install "uvicorn[standard]"
|
||||
|
||||
</div>
|
||||
|
||||
## Example
|
||||
## Пример
|
||||
|
||||
### Create it
|
||||
### Создание
|
||||
|
||||
* Create a file `main.py` with:
|
||||
* Создайте файл `main.py` со следующим содержимым:
|
||||
|
||||
```Python
|
||||
from typing import Union
|
||||
@@ -167,9 +165,9 @@ def read_item(item_id: int, q: Union[str, None] = None):
|
||||
```
|
||||
|
||||
<details markdown="1">
|
||||
<summary>Or use <code>async def</code>...</summary>
|
||||
<summary>Или используйте <code>async def</code>...</summary>
|
||||
|
||||
If your code uses `async` / `await`, use `async def`:
|
||||
Если ваш код использует `async` / `await`, используйте `async def`:
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
from typing import Union
|
||||
@@ -189,15 +187,15 @@ async def read_item(item_id: int, q: Union[str, None] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
**Note**:
|
||||
**Примечание**:
|
||||
|
||||
If you don't know, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
|
||||
Если вы не знаете, проверьте раздел _"Торопитесь?"_ <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">в документации об `async` и `await`</a>.
|
||||
|
||||
</details>
|
||||
|
||||
### Run it
|
||||
### Запуск
|
||||
|
||||
Run the server with:
|
||||
Запустите сервер с помощью:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
@@ -214,54 +212,54 @@ INFO: Application startup complete.
|
||||
</div>
|
||||
|
||||
<details markdown="1">
|
||||
<summary>About the command <code>uvicorn main:app --reload</code>...</summary>
|
||||
<summary>О команде <code>uvicorn main:app --reload</code>...</summary>
|
||||
|
||||
The command `uvicorn main:app` refers to:
|
||||
Команда `uvicorn main:app` относится к:
|
||||
|
||||
* `main`: the file `main.py` (the Python "module").
|
||||
* `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
|
||||
* `--reload`: make the server restart after code changes. Only do this for development.
|
||||
* `main`: файл `main.py` (модуль Python).
|
||||
* `app`: объект, созданный внутри `main.py` с помощью строки `app = FastAPI()`.
|
||||
* `--reload`: перезапуск сервера после изменения кода. Делайте это только во время разработки.
|
||||
|
||||
</details>
|
||||
|
||||
### Check it
|
||||
### Проверка
|
||||
|
||||
Open your browser at <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
|
||||
Откройте браузер на <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
|
||||
|
||||
You will see the JSON response as:
|
||||
Вы увидите следующий JSON ответ:
|
||||
|
||||
```JSON
|
||||
{"item_id": 5, "q": "somequery"}
|
||||
```
|
||||
|
||||
You already created an API that:
|
||||
Вы уже создали API, который:
|
||||
|
||||
* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`.
|
||||
* Both _paths_ take `GET` <em>operations</em> (also known as HTTP _methods_).
|
||||
* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`.
|
||||
* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`.
|
||||
* Получает HTTP-запросы по _путям_ `/` и `/items/{item_id}`.
|
||||
* И первый и второй _путь_ используют `GET` <em>операции</em> (также известные как HTTP _методы_).
|
||||
* _путь_ `/items/{item_id}` имеет _параметр пути_ `item_id`, который должен быть `int`.
|
||||
* _путь_ `/items/{item_id}` имеет необязательный `str` _параметр запроса_ `q`.
|
||||
|
||||
### Interactive API docs
|
||||
### Интерактивная документация по API
|
||||
|
||||
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
Перейдите на <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
You will see the automatic interactive API documentation (provided by <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
|
||||
Вы увидите автоматическую интерактивную документацию API (предоставленную <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
|
||||
|
||||

|
||||
|
||||
### Alternative API docs
|
||||
### Альтернативная документация по API
|
||||
|
||||
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
А теперь перейдите на <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
You will see the alternative automatic documentation (provided by <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
Вы увидите альтернативную автоматическую документацию (предоставленную <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
|
||||

|
||||
|
||||
## Example upgrade
|
||||
## Пример обновления
|
||||
|
||||
Now modify the file `main.py` to receive a body from a `PUT` request.
|
||||
Теперь измените файл `main.py`, чтобы получить тело ответа из `PUT` запроса.
|
||||
|
||||
Declare the body using standard Python types, thanks to Pydantic.
|
||||
Объявите тело, используя стандартную типизацию Python, спасибо Pydantic.
|
||||
|
||||
```Python hl_lines="4 9-12 25-27"
|
||||
from typing import Union
|
||||
@@ -293,174 +291,173 @@ def update_item(item_id: int, item: Item):
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
The server should reload automatically (because you added `--reload` to the `uvicorn` command above).
|
||||
Сервер должен перезагрузиться автоматически (потому что вы добавили `--reload` к команде `uvicorn` выше).
|
||||
|
||||
### Interactive API docs upgrade
|
||||
### Интерактивное обновление документации API
|
||||
|
||||
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
Перейдите на <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
* The interactive API documentation will be automatically updated, including the new body:
|
||||
* Интерактивная документация API будет автоматически обновляться, включая новое тело:
|
||||
|
||||

|
||||
|
||||
* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API:
|
||||
* Нажмите на кнопку "Try it out", это позволит вам заполнить параметры и напрямую взаимодействовать с API:
|
||||
|
||||

|
||||
|
||||
* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen:
|
||||
* Затем нажмите кнопку "Execute", пользовательский интерфейс свяжется с вашим API, отправит параметры, получит результаты и отобразит их на экране:
|
||||
|
||||

|
||||
|
||||
### Alternative API docs upgrade
|
||||
### Альтернативное обновление документации API
|
||||
|
||||
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
А теперь перейдите на <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
* The alternative documentation will also reflect the new query parameter and body:
|
||||
* Альтернативная документация также будет отражать новый параметр и тело запроса:
|
||||
|
||||

|
||||
|
||||
### Recap
|
||||
### Подведём итоги
|
||||
|
||||
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
|
||||
Таким образом, вы объявляете **один раз** типы параметров, тело и т. д. в качестве параметров функции.
|
||||
|
||||
You do that with standard modern Python types.
|
||||
Вы делаете это испльзуя стандартную современную типизацию Python.
|
||||
|
||||
You don't have to learn a new syntax, the methods or classes of a specific library, etc.
|
||||
Вам не нужно изучать новый синтаксис, методы или классы конкретной библиотеки и т. д.
|
||||
|
||||
Just standard **Python 3.6+**.
|
||||
Только стандартный **Python 3.6+**.
|
||||
|
||||
For example, for an `int`:
|
||||
Например, для `int`:
|
||||
|
||||
```Python
|
||||
item_id: int
|
||||
```
|
||||
|
||||
or for a more complex `Item` model:
|
||||
или для более сложной модели `Item`:
|
||||
|
||||
```Python
|
||||
item: Item
|
||||
```
|
||||
|
||||
...and with that single declaration you get:
|
||||
... и с этим единственным объявлением вы получаете:
|
||||
|
||||
* Editor support, including:
|
||||
* Completion.
|
||||
* Type checks.
|
||||
* Validation of data:
|
||||
* Automatic and clear errors when the data is invalid.
|
||||
* Validation even for deeply nested JSON objects.
|
||||
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network to Python data and types. Reading from:
|
||||
* Поддержка редактора, в том числе:
|
||||
* Автозавершение.
|
||||
* Проверка типов.
|
||||
* Валидация данных:
|
||||
* Автоматические и четкие ошибки, когда данные недействительны.
|
||||
* Проверка даже для глубоко вложенных объектов JSON.
|
||||
* <abbr title="также известный как: сериализация, синтаксический анализ, маршалинг">Преобразование</abbr> входных данных: поступающие из сети в объекты Python с соблюдением типов. Чтение из:
|
||||
* JSON.
|
||||
* Path parameters.
|
||||
* Query parameters.
|
||||
* Параметров пути.
|
||||
* Параметров запроса.
|
||||
* Cookies.
|
||||
* Headers.
|
||||
* Forms.
|
||||
* Files.
|
||||
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of output data: converting from Python data and types to network data (as JSON):
|
||||
* Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc).
|
||||
* `datetime` objects.
|
||||
* `UUID` objects.
|
||||
* Database models.
|
||||
* ...and many more.
|
||||
* Automatic interactive API documentation, including 2 alternative user interfaces:
|
||||
* Заголовков.
|
||||
* Форм.
|
||||
* Файлов.
|
||||
* <abbr title="также известный как: сериализация, синтаксический анализ, маршалинг">Преобразование</abbr> выходных данных: преобразование объектов Python в данные передаваемые по сети интернет (такие как JSON):
|
||||
* Преобразование типов Python (`str`, `int`, `float`, `bool`, `list`, и т.д.).
|
||||
* Объекты `datetime`.
|
||||
* Объекты `UUID`.
|
||||
* Модели баз данных.
|
||||
* ...и многое другое.
|
||||
* Автоматическая интерактивная документация по API, включая 2 альтернативных пользовательских интерфейса:
|
||||
* Swagger UI.
|
||||
* ReDoc.
|
||||
|
||||
---
|
||||
|
||||
Coming back to the previous code example, **FastAPI** will:
|
||||
Возвращаясь к предыдущему примеру кода, **FastAPI** будет:
|
||||
|
||||
* Validate that there is an `item_id` in the path for `GET` and `PUT` requests.
|
||||
* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests.
|
||||
* If it is not, the client will see a useful, clear error.
|
||||
* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests.
|
||||
* As the `q` parameter is declared with `= None`, it is optional.
|
||||
* Without the `None` it would be required (as is the body in the case with `PUT`).
|
||||
* For `PUT` requests to `/items/{item_id}`, Read the body as JSON:
|
||||
* Check that it has a required attribute `name` that should be a `str`.
|
||||
* Check that it has a required attribute `price` that has to be a `float`.
|
||||
* Check that it has an optional attribute `is_offer`, that should be a `bool`, if present.
|
||||
* All this would also work for deeply nested JSON objects.
|
||||
* Convert from and to JSON automatically.
|
||||
* Document everything with OpenAPI, that can be used by:
|
||||
* Interactive documentation systems.
|
||||
* Automatic client code generation systems, for many languages.
|
||||
* Provide 2 interactive documentation web interfaces directly.
|
||||
* Проверять наличие `item_id` в пути для запросов `GET` и `PUT`.
|
||||
* Проверять, что `item_id` имеет тип `int` для запросов `GET` и `PUT`.
|
||||
* Если это не так, клиент увидит полезную чёткую ошибку.
|
||||
* Проверять, есть ли необязательный параметр запроса с именем `q` (например, `http://127.0.0.1:8000/items/foo?q=somequery`) для `GET` запросов.
|
||||
* Поскольку параметр `q` объявлен с `= None`, он является необязательным.
|
||||
* Без `None` он был бы необходим (как тело в случае с `PUT`).
|
||||
* Для `PUT` запросов к `/items/{item_id}` читать тело как JSON:
|
||||
* Проверять, что у него есть обязательный атрибут `name`, который должен быть `str`.
|
||||
* Проверять, что у него есть обязательный атрибут `price`, который должен быть `float`.
|
||||
* Проверять, что у него есть необязательный атрибут `is_offer`, который должен быть `bool`, если он присутствует.
|
||||
* Все это также будет работать для глубоко вложенных объектов JSON.
|
||||
* Преобразовывать из и в JSON автоматически.
|
||||
* Документировать с помощью OpenAPI все, что может быть использовано:
|
||||
* Системы интерактивной документации.
|
||||
* Системы автоматической генерации клиентского кода для многих языков.
|
||||
* Обеспечит 2 интерактивных веб-интерфейса документации напрямую.
|
||||
|
||||
---
|
||||
|
||||
We just scratched the surface, but you already get the idea of how it all works.
|
||||
Мы только немного копнули поверхность, но вы уже поняли, как все это работает.
|
||||
|
||||
Try changing the line with:
|
||||
Попробуйте изменить строку с помощью:
|
||||
|
||||
```Python
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
...from:
|
||||
...из:
|
||||
|
||||
```Python
|
||||
... "item_name": item.name ...
|
||||
```
|
||||
|
||||
...to:
|
||||
...в:
|
||||
|
||||
```Python
|
||||
... "item_price": item.price ...
|
||||
```
|
||||
|
||||
...and see how your editor will auto-complete the attributes and know their types:
|
||||
... и посмотрите, как ваш редактор будет автоматически заполнять атрибуты и узнавать их типы:
|
||||
|
||||

|
||||
|
||||
For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
|
||||
Более полный пример с дополнительными функциями см. в <a href="https://fastapi.tiangolo.com/tutorial/">Учебное руководство - Руководство пользователя</a>.
|
||||
|
||||
**Spoiler alert**: the tutorial - user guide includes:
|
||||
**Осторожно, спойлер**: руководство пользователя включает в себя:
|
||||
|
||||
* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**.
|
||||
* How to set **validation constraints** as `maximum_length` or `regex`.
|
||||
* A very powerful and easy to use **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
|
||||
* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth.
|
||||
* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic).
|
||||
* Many extra features (thanks to Starlette) as:
|
||||
* **WebSockets**
|
||||
* **GraphQL**
|
||||
* extremely easy tests based on `requests` and `pytest`
|
||||
* Объявление **параметров** из других мест, таких как: **заголовки**, **cookies**, **поля формы** и **файлы**.
|
||||
* Как установить **ограничительные проверки** такие как `maximum_length` или `regex`.
|
||||
* Очень мощная и простая в использовании система **<abbr title="также известная как компоненты, ресурсы, провайдеры, сервисы, инъекции">внедрения зависимостей</abbr>**.
|
||||
* Безопасность и аутентификация, включая поддержку **OAuth2** с **токенами JWT** и **HTTP Basic** аутентификацию.
|
||||
* Более продвинутые (но столь же простые) методы объявления **глубоко вложенных моделей JSON** (спасибо Pydantic).
|
||||
* **GraphQL** интеграция с <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> и другими библиотеками.
|
||||
* Множество дополнительных функций (благодаря Starlette), таких как:
|
||||
* **Веб-сокеты**
|
||||
* очень простые тесты на основе `requests` и `pytest`
|
||||
* **CORS**
|
||||
* **Cookie Sessions**
|
||||
* ...and more.
|
||||
* **Cookie сеансы(сессии)**
|
||||
* ...и многое другое.
|
||||
|
||||
## Performance
|
||||
## Производительность
|
||||
|
||||
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
|
||||
Независимые тесты TechEmpower показывают приложения **FastAPI**, работающие под управлением Uvicorn, как <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">один из самых быстрых доступных фреймворков Python</a>, уступающий только самим Starlette и Uvicorn (используемых внутри FastAPI). (*)
|
||||
|
||||
To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
|
||||
Чтобы узнать больше об этом, см. раздел <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Тесты производительности</a>.
|
||||
|
||||
## Optional Dependencies
|
||||
## Необязательные зависимости
|
||||
|
||||
Used by Pydantic:
|
||||
Используется Pydantic:
|
||||
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - for faster JSON <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>.
|
||||
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - for email validation.
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - для более быстрого JSON <abbr title="преобразования строки, полученной из HTTP-запроса, в данные Python">"парсинга"</abbr>.
|
||||
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - для проверки электронной почты.
|
||||
|
||||
Used by Starlette:
|
||||
Используется Starlette:
|
||||
|
||||
* <a href="https://requests.readthedocs.io" target="_blank"><code>requests</code></a> - Required if you want to use the `TestClient`.
|
||||
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Required if you want to use the default template configuration.
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Required if you want to support form <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>, with `request.form()`.
|
||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Required for `SessionMiddleware` support.
|
||||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI).
|
||||
* <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - Required for `GraphQLApp` support.
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
|
||||
* <a href="https://requests.readthedocs.io" target="_blank"><code>requests</code></a> - Обязательно, если вы хотите использовать `TestClient`.
|
||||
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Обязательно, если вы хотите использовать конфигурацию шаблона по умолчанию.
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Обязательно, если вы хотите поддерживать форму <abbr title="преобразование строки, полученной из HTTP-запроса, в данные Python">"парсинга"</abbr> с помощью `request.form()`.
|
||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Обязательно, для поддержки `SessionMiddleware`.
|
||||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Обязательно, для поддержки `SchemaGenerator` Starlette (возможно, вам это не нужно с FastAPI).
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Обязательно, если вы хотите использовать `UJSONResponse`.
|
||||
|
||||
Used by FastAPI / Starlette:
|
||||
Используется FastAPI / Starlette:
|
||||
|
||||
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application.
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
|
||||
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - сервер, который загружает и обслуживает ваше приложение.
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Обязательно, если вы хотите использовать `ORJSONResponse`.
|
||||
|
||||
You can install all of these with `pip install fastapi[all]`.
|
||||
Вы можете установить все это с помощью `pip install "fastapi[all]"`.
|
||||
|
||||
## License
|
||||
## Лицензия
|
||||
|
||||
This project is licensed under the terms of the MIT license.
|
||||
Этот проект распространяется на условиях лицензии MIT.
|
||||
|
||||
@@ -58,11 +58,16 @@ nav:
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
- features.md
|
||||
- fastapi-people.md
|
||||
- python-types.md
|
||||
- Учебник - руководство пользователя:
|
||||
- tutorial/background-tasks.md
|
||||
- external-links.md
|
||||
- async.md
|
||||
- Развёртывание:
|
||||
- deployment/index.md
|
||||
- deployment/versions.md
|
||||
- external-links.md
|
||||
markdown_extensions:
|
||||
- toc:
|
||||
permalink: true
|
||||
|
||||
@@ -111,7 +111,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
|
||||
|
||||
## Requirements
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI stands on the shoulders of giants:
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
|
||||
|
||||
## Requirements
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI stands on the shoulders of giants:
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ Eğer API yerine <abbr title="Command Line Interface">komut satırı uygulaması
|
||||
|
||||
## Gereksinimler
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI iki devin omuzları üstünde duruyor:
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
|
||||
|
||||
## Requirements
|
||||
|
||||
Python 3.6+
|
||||
Python 3.7+
|
||||
|
||||
FastAPI stands on the shoulders of giants:
|
||||
|
||||
|
||||
37
docs/zh/docs/advanced/wsgi.md
Normal file
37
docs/zh/docs/advanced/wsgi.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# 包含 WSGI - Flask,Django,其它
|
||||
|
||||
您可以挂载多个 WSGI 应用,正如您在 [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}, [Behind a Proxy](./behind-a-proxy.md){.internal-link target=_blank} 中所看到的那样。
|
||||
|
||||
为此, 您可以使用 `WSGIMiddleware` 来包装你的 WSGI 应用,如:Flask,Django,等等。
|
||||
|
||||
## 使用 `WSGIMiddleware`
|
||||
|
||||
您需要导入 `WSGIMiddleware`。
|
||||
|
||||
然后使用该中间件包装 WSGI 应用(例如 Flask)。
|
||||
|
||||
之后将其挂载到某一个路径下。
|
||||
|
||||
```Python hl_lines="2-3 22"
|
||||
{!../../../docs_src/wsgi/tutorial001.py!}
|
||||
```
|
||||
|
||||
## 检查
|
||||
|
||||
现在,所有定义在 `/v1/` 路径下的请求将会被 Flask 应用处理。
|
||||
|
||||
其余的请求则会被 **FastAPI** 处理。
|
||||
|
||||
如果您使用 Uvicorn 运行应用实例并且访问 <a href="http://localhost:8000/v1/" class="external-link" target="_blank">http://localhost:8000/v1/</a>,您将会看到由 Flask 返回的响应:
|
||||
|
||||
```txt
|
||||
Hello, World from Flask!
|
||||
```
|
||||
|
||||
并且如果您访问 <a href="http://localhost:8000/v2" class="external-link" target="_blank">http://localhost:8000/v2</a>,您将会看到由 FastAPI 返回的响应:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"message": "Hello World"
|
||||
}
|
||||
```
|
||||
@@ -88,61 +88,29 @@ $ python -m venv env
|
||||
!!! tip
|
||||
每一次你在该环境下使用 `pip` 安装了新软件包时,请再次激活该环境。
|
||||
|
||||
这样可以确保你在使用由该软件包安装的终端程序(如 `flit`)时使用的是当前虚拟环境中的程序,而不是其他的可能是全局安装的程序。
|
||||
这样可以确保你在使用由该软件包安装的终端程序时使用的是当前虚拟环境中的程序,而不是其他的可能是全局安装的程序。
|
||||
|
||||
### Flit
|
||||
### pip
|
||||
|
||||
**FastAPI** 使用 <a href="https://flit.readthedocs.io/en/latest/index.html" class="external-link" target="_blank">Flit</a> 来构建、打包和发布项目。
|
||||
|
||||
如上所述激活环境后,安装 `flit`:
|
||||
如上所述激活环境后:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install flit
|
||||
$ pip install -e ."[dev,doc,test]"
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
现在重新激活环境,以确保你正在使用的是刚刚安装的 `flit`(而不是全局环境的)。
|
||||
|
||||
然后使用 `flit` 来安装开发依赖:
|
||||
|
||||
=== "Linux, macOS"
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ flit install --deps develop --symlink
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
=== "Windows"
|
||||
|
||||
If you are on Windows, use `--pth-file` instead of `--symlink`:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ flit install --deps develop --pth-file
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
这将在虚拟环境中安装所有依赖和本地版本的 FastAPI。
|
||||
|
||||
#### 使用本地 FastAPI
|
||||
|
||||
如果你创建一个导入并使用 FastAPI 的 Python 文件,然后使用虚拟环境中的 Python 运行它,它将使用你本地的 FastAPI 源码。
|
||||
|
||||
并且如果你更改该本地 FastAPI 的源码,由于它是通过 `--symlink` (或 Windows 上的 `--pth-file`)安装的,当你再次运行那个 Python 文件,它将使用你刚刚编辑过的最新版本的 FastAPI。
|
||||
并且如果你更改该本地 FastAPI 的源码,由于它是通过 `-e` 安装的,当你再次运行那个 Python 文件,它将使用你刚刚编辑过的最新版本的 FastAPI。
|
||||
|
||||
这样,你不必再去重新"安装"你的本地版本即可测试所有更改。
|
||||
|
||||
@@ -160,7 +128,7 @@ $ bash scripts/format.sh
|
||||
|
||||
它还会自动对所有导入代码进行整理。
|
||||
|
||||
为了使整理正确进行,你需要在当前环境中安装本地的 FastAPI,即在运行上述段落中的命令时添加 `--symlink`(或 Windows 上的 `--pth-file`)。
|
||||
为了使整理正确进行,你需要在当前环境中安装本地的 FastAPI,即在运行上述段落中的命令时添加 `-e`。
|
||||
|
||||
### 格式化导入
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ John Doe
|
||||
|
||||
这表示:
|
||||
|
||||
* 变量 `items_t` 是一个 `tuple`,其中的每个元素都是 `int` 类型。
|
||||
* 变量 `items_t` 是一个 `tuple`,其中的前两个元素都是 `int` 类型, 最后一个元素是 `str` 类型。
|
||||
* 变量 `items_s` 是一个 `set`,其中的每个元素都是 `bytes` 类型。
|
||||
|
||||
#### 字典
|
||||
|
||||
247
docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md
Normal file
247
docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md
Normal file
@@ -0,0 +1,247 @@
|
||||
# 类作为依赖项
|
||||
|
||||
在深入探究 **依赖注入** 系统之前,让我们升级之前的例子。
|
||||
|
||||
## 来自前一个例子的`dict`
|
||||
|
||||
在前面的例子中, 我们从依赖项 ("可依赖对象") 中返回了一个 `dict`:
|
||||
|
||||
=== "Python 3.6 以及 以上"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 以及以上"
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
但是后面我们在路径操作函数的参数 `commons` 中得到了一个 `dict`。
|
||||
|
||||
我们知道编辑器不能为 `dict` 提供很多支持(比如补全),因为编辑器不知道 `dict` 的键和值类型。
|
||||
|
||||
对此,我们可以做的更好...
|
||||
|
||||
## 什么构成了依赖项?
|
||||
|
||||
到目前为止,您看到的依赖项都被声明为函数。
|
||||
|
||||
但这并不是声明依赖项的唯一方法(尽管它可能是更常见的方法)。
|
||||
|
||||
关键因素是依赖项应该是 "可调用对象"。
|
||||
|
||||
Python 中的 "**可调用对象**" 是指任何 Python 可以像函数一样 "调用" 的对象。
|
||||
|
||||
所以,如果你有一个对象 `something` (可能*不是*一个函数),你可以 "调用" 它(执行它),就像:
|
||||
|
||||
```Python
|
||||
something()
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
```Python
|
||||
something(some_argument, some_keyword_argument="foo")
|
||||
```
|
||||
|
||||
这就是 "可调用对象"。
|
||||
|
||||
## 类作为依赖项
|
||||
|
||||
您可能会注意到,要创建一个 Python 类的实例,您可以使用相同的语法。
|
||||
|
||||
举个例子:
|
||||
|
||||
```Python
|
||||
class Cat:
|
||||
def __init__(self, name: str):
|
||||
self.name = name
|
||||
|
||||
|
||||
fluffy = Cat(name="Mr Fluffy")
|
||||
```
|
||||
|
||||
在这个例子中, `fluffy` 是一个 `Cat` 类的实例。
|
||||
|
||||
为了创建 `fluffy`,你调用了 `Cat` 。
|
||||
|
||||
所以,Python 类也是 **可调用对象**。
|
||||
|
||||
因此,在 **FastAPI** 中,你可以使用一个 Python 类作为一个依赖项。
|
||||
|
||||
实际上 FastAPI 检查的是它是一个 "可调用对象"(函数,类或其他任何类型)以及定义的参数。
|
||||
|
||||
如果您在 **FastAPI** 中传递一个 "可调用对象" 作为依赖项,它将分析该 "可调用对象" 的参数,并以处理路径操作函数的参数的方式来处理它们。包括子依赖项。
|
||||
|
||||
这也适用于完全没有参数的可调用对象。这与不带参数的路径操作函数一样。
|
||||
|
||||
所以,我们可以将上面的依赖项 "可依赖对象" `common_parameters` 更改为类 `CommonQueryParams`:
|
||||
|
||||
=== "Python 3.6 以及 以上"
|
||||
|
||||
```Python hl_lines="11-15"
|
||||
{!> ../../../docs_src/dependencies/tutorial002.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 以及 以上"
|
||||
|
||||
```Python hl_lines="9-13"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
注意用于创建类实例的 `__init__` 方法:
|
||||
|
||||
=== "Python 3.6 以及 以上"
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/dependencies/tutorial002.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 以及 以上"
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
...它与我们以前的 `common_parameters` 具有相同的参数:
|
||||
|
||||
=== "Python 3.6 以及 以上"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 以及 以上"
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
这些参数就是 **FastAPI** 用来 "处理" 依赖项的。
|
||||
|
||||
在两个例子下,都有:
|
||||
|
||||
* 一个可选的 `q` 查询参数,是 `str` 类型。
|
||||
* 一个 `skip` 查询参数,是 `int` 类型,默认值为 `0`。
|
||||
* 一个 `limit` 查询参数,是 `int` 类型,默认值为 `100`。
|
||||
|
||||
在两个例子下,数据都将被转换、验证、在 OpenAPI schema 上文档化,等等。
|
||||
|
||||
## 使用它
|
||||
|
||||
现在,您可以使用这个类来声明你的依赖项了。
|
||||
|
||||
=== "Python 3.6 以及 以上"
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial002.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 以及 以上"
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
**FastAPI** 调用 `CommonQueryParams` 类。这将创建该类的一个 "实例",该实例将作为参数 `commons` 被传递给你的函数。
|
||||
|
||||
## 类型注解 vs `Depends`
|
||||
|
||||
注意,我们在上面的代码中编写了两次`CommonQueryParams`:
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||
```
|
||||
|
||||
最后的 `CommonQueryParams`:
|
||||
|
||||
```Python
|
||||
... = Depends(CommonQueryParams)
|
||||
```
|
||||
|
||||
...实际上是 **Fastapi** 用来知道依赖项是什么的。
|
||||
|
||||
FastAPI 将从依赖项中提取声明的参数,这才是 FastAPI 实际调用的。
|
||||
|
||||
---
|
||||
|
||||
在本例中,第一个 `CommonQueryParams` :
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams ...
|
||||
```
|
||||
|
||||
...对于 **FastAPI** 没有任何特殊的意义。FastAPI 不会使用它进行数据转换、验证等 (因为对于这,它使用 `= Depends(CommonQueryParams)`)。
|
||||
|
||||
你实际上可以只这样编写:
|
||||
|
||||
```Python
|
||||
commons = Depends(CommonQueryParams)
|
||||
```
|
||||
|
||||
..就像:
|
||||
|
||||
=== "Python 3.6 以及 以上"
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial003.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 以及 以上"
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/dependencies/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
但是声明类型是被鼓励的,因为那样你的编辑器就会知道将传递什么作为参数 `commons` ,然后它可以帮助你完成代码,类型检查,等等:
|
||||
|
||||
<img src="/img/tutorial/dependencies/image02.png">
|
||||
|
||||
## 快捷方式
|
||||
|
||||
但是您可以看到,我们在这里有一些代码重复了,编写了`CommonQueryParams`两次:
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||
```
|
||||
|
||||
**FastAPI** 为这些情况提供了一个快捷方式,在这些情况下,依赖项 *明确地* 是一个类,**FastAPI** 将 "调用" 它来创建类本身的一个实例。
|
||||
|
||||
对于这些特定的情况,您可以跟随以下操作:
|
||||
|
||||
不是写成这样:
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||
```
|
||||
|
||||
...而是这样写:
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends()
|
||||
```
|
||||
|
||||
您声明依赖项作为参数的类型,并使用 `Depends()` 作为该函数的参数的 "默认" 值(在 `=` 之后),而在 `Depends()` 中没有任何参数,而不是在 `Depends(CommonQueryParams)` 编写完整的类。
|
||||
|
||||
同样的例子看起来像这样:
|
||||
|
||||
=== "Python 3.6 以及 以上"
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial004.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 以及 以上"
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/dependencies/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
... **FastAPI** 会知道怎么处理。
|
||||
|
||||
!!! tip
|
||||
如果这看起来更加混乱而不是更加有帮助,那么请忽略它,你不*需要*它。
|
||||
|
||||
这只是一个快捷方式。因为 **FastAPI** 关心的是帮助您减少代码重复。
|
||||
42
docs/zh/docs/tutorial/encoder.md
Normal file
42
docs/zh/docs/tutorial/encoder.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# JSON 兼容编码器
|
||||
|
||||
在某些情况下,您可能需要将数据类型(如Pydantic模型)转换为与JSON兼容的数据类型(如`dict`、`list`等)。
|
||||
|
||||
比如,如果您需要将其存储在数据库中。
|
||||
|
||||
对于这种要求, **FastAPI**提供了`jsonable_encoder()`函数。
|
||||
|
||||
## 使用`jsonable_encoder`
|
||||
|
||||
让我们假设你有一个数据库名为`fake_db`,它只能接收与JSON兼容的数据。
|
||||
|
||||
例如,它不接收`datetime`这类的对象,因为这些对象与JSON不兼容。
|
||||
|
||||
因此,`datetime`对象必须将转换为包含<a href="https://en.wikipedia.org/wiki/ISO_8601" class="external-link" target="_blank">ISO格式化</a>的`str`类型对象。
|
||||
|
||||
同样,这个数据库也不会接收Pydantic模型(带有属性的对象),而只接收`dict`。
|
||||
|
||||
对此你可以使用`jsonable_encoder`。
|
||||
|
||||
它接收一个对象,比如Pydantic模型,并会返回一个JSON兼容的版本:
|
||||
|
||||
=== "Python 3.6 and above"
|
||||
|
||||
```Python hl_lines="5 22"
|
||||
{!> ../../../docs_src/encoder/tutorial001.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 and above"
|
||||
|
||||
```Python hl_lines="4 21"
|
||||
{!> ../../../docs_src/encoder/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
在这个例子中,它将Pydantic模型转换为`dict`,并将`datetime`转换为`str`。
|
||||
|
||||
调用它的结果后就可以使用Python标准编码中的<a href="https://docs.python.org/3/library/json.html#json.dumps" class="external-link" target="_blank">`json.dumps()`</a>。
|
||||
|
||||
这个操作不会返回一个包含JSON格式(作为字符串)数据的庞大的`str`。它将返回一个Python标准数据结构(例如`dict`),其值和子值都与JSON兼容。
|
||||
|
||||
!!! note
|
||||
`jsonable_encoder`实际上是FastAPI内部用来转换数据的。但是它在许多其他场景中也很有用。
|
||||
@@ -104,7 +104,7 @@ q: str
|
||||
代替:
|
||||
|
||||
```Python
|
||||
q: str = None
|
||||
q: Union[str, None] = None
|
||||
```
|
||||
|
||||
但是现在我们正在用 `Query` 声明它,例如:
|
||||
@@ -113,17 +113,51 @@ q: str = None
|
||||
q: Union[str, None] = Query(default=None, min_length=3)
|
||||
```
|
||||
|
||||
因此,当你在使用 `Query` 且需要声明一个值是必需的时,可以将 `...` 用作第一个参数值:
|
||||
因此,当你在使用 `Query` 且需要声明一个值是必需的时,只需不声明默认参数:
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/query_params_str_validations/tutorial006.py!}
|
||||
```
|
||||
|
||||
### 使用省略号(`...`)声明必需参数
|
||||
|
||||
有另一种方法可以显式的声明一个值是必需的,即将默认参数的默认值设为 `...` :
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/query_params_str_validations/tutorial006b.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
如果你之前没见过 `...` 这种用法:它是一个特殊的单独值,它是 <a href="https://docs.python.org/3/library/constants.html#Ellipsis" class="external-link" target="_blank">Python 的一部分并且被称为「省略号」</a>。
|
||||
Pydantic 和 FastAPI 使用它来显式的声明需要一个值。
|
||||
|
||||
这将使 **FastAPI** 知道此查询参数是必需的。
|
||||
|
||||
### 使用`None`声明必需参数
|
||||
|
||||
你可以声明一个参数可以接收`None`值,但它仍然是必需的。这将强制客户端发送一个值,即使该值是`None`。
|
||||
|
||||
为此,你可以声明`None`是一个有效的类型,并仍然使用`default=...`:
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../../docs_src/query_params_str_validations/tutorial006c.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
Pydantic 是 FastAPI 中所有数据验证和序列化的核心,当你在没有设默认值的情况下使用 `Optional` 或 `Union[Something, None]` 时,它具有特殊行为,你可以在 Pydantic 文档中阅读有关<a href="https://pydantic-docs.helpmanual.io/usage/models/#required-optional-fields" class="external-link" target="_blank">必需可选字段</a>的更多信息。
|
||||
|
||||
### 使用Pydantic中的`Required`代替省略号(`...`)
|
||||
|
||||
如果你觉得使用 `...` 不舒服,你也可以从 Pydantic 导入并使用 `Required`:
|
||||
|
||||
```Python hl_lines="2 8"
|
||||
{!../../../docs_src/query_params_str_validations/tutorial006d.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
请记住,在大多数情况下,当你需要某些东西时,可以简单地省略 `default` 参数,因此你通常不必使用 `...` 或 `Required`
|
||||
|
||||
|
||||
## 查询参数列表 / 多个值
|
||||
|
||||
当你使用 `Query` 显式地定义查询参数时,你还可以声明它去接收一组值,或换句话来说,接收多个值。
|
||||
|
||||
@@ -44,9 +44,9 @@
|
||||
|
||||
不过,很多情况下,`UploadFile` 更好用。
|
||||
|
||||
## 含 `UploadFile` 的 `File` 参数
|
||||
## 含 `UploadFile` 的文件参数
|
||||
|
||||
定义 `File` 参数时使用 `UploadFile`:
|
||||
定义文件参数时使用 `UploadFile`:
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!../../../docs_src/request_files/tutorial001.py!}
|
||||
@@ -94,7 +94,7 @@ contents = myfile.file.read()
|
||||
|
||||
!!! note "`async` 技术细节"
|
||||
|
||||
使用 `async` 方法时,**FastAPI** 在线程池中执行文件方法,并 `awiat` 操作完成。
|
||||
使用 `async` 方法时,**FastAPI** 在线程池中执行文件方法,并 `await` 操作完成。
|
||||
|
||||
!!! note "Starlette 技术细节"
|
||||
|
||||
@@ -120,6 +120,30 @@ contents = myfile.file.read()
|
||||
|
||||
这不是 **FastAPI** 的问题,而是 HTTP 协议的规定。
|
||||
|
||||
## 可选文件上传
|
||||
|
||||
您可以通过使用标准类型注解并将 None 作为默认值的方式将一个文件参数设为可选:
|
||||
|
||||
=== "Python 3.6 及以上版本"
|
||||
|
||||
```Python hl_lines="9 17"
|
||||
{!> ../../../docs_src/request_files/tutorial001_02.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 及以上版本"
|
||||
|
||||
```Python hl_lines="7 14"
|
||||
{!> ../../../docs_src/request_files/tutorial001_02_py310.py!}
|
||||
```
|
||||
|
||||
## 带有额外元数据的 `UploadFile`
|
||||
|
||||
您也可以将 `File()` 与 `UploadFile` 一起使用,例如,设置额外的元数据:
|
||||
|
||||
```Python hl_lines="13"
|
||||
{!../../../docs_src/request_files/tutorial001_03.py!}
|
||||
```
|
||||
|
||||
## 多文件上传
|
||||
|
||||
FastAPI 支持同时上传多个文件。
|
||||
@@ -128,19 +152,20 @@ FastAPI 支持同时上传多个文件。
|
||||
|
||||
上传多个文件时,要声明含 `bytes` 或 `UploadFile` 的列表(`List`):
|
||||
|
||||
```Python hl_lines="10 15"
|
||||
{!../../../docs_src/request_files/tutorial002.py!}
|
||||
```
|
||||
=== "Python 3.6 及以上版本"
|
||||
|
||||
```Python hl_lines="10 15"
|
||||
{!> ../../../docs_src/request_files/tutorial002.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 及以上版本"
|
||||
|
||||
```Python hl_lines="8 13"
|
||||
{!> ../../../docs_src/request_files/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
接收的也是含 `bytes` 或 `UploadFile` 的列表(`list`)。
|
||||
|
||||
!!! note "笔记"
|
||||
|
||||
注意,截至 2019 年 4 月 14 日,Swagger UI 不支持在同一个表单字段中上传多个文件。详见 <a href="https://github.com/swagger-api/swagger-ui/issues/4276" class="external-link" target="_blank">#4276</a> 和 <a href="https://github.com/swagger-api/swagger-ui/issues/3641" class="external-link" target="_blank">#3641</a>.
|
||||
|
||||
不过,**FastAPI** 已通过 OpenAPI 标准与之兼容。
|
||||
|
||||
因此,只要 Swagger UI 或任何其他支持 OpenAPI 的工具支持多文件上传,都将与 **FastAPI** 兼容。
|
||||
|
||||
!!! note "技术细节"
|
||||
|
||||
@@ -148,6 +173,22 @@ FastAPI 支持同时上传多个文件。
|
||||
|
||||
`fastapi.responses` 其实与 `starlette.responses` 相同,只是为了方便开发者调用。实际上,大多数 **FastAPI** 的响应都直接从 Starlette 调用。
|
||||
|
||||
### 带有额外元数据的多文件上传
|
||||
|
||||
和之前的方式一样, 您可以为 `File()` 设置额外参数, 即使是 `UploadFile`:
|
||||
|
||||
=== "Python 3.6 及以上版本"
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/request_files/tutorial003.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 及以上版本"
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/request_files/tutorial003_py39.py!}
|
||||
```
|
||||
|
||||
## 小结
|
||||
|
||||
本节介绍了如何用 `File` 把上传文件声明为(表单数据的)输入参数。
|
||||
|
||||
@@ -110,7 +110,7 @@ OAuth2 的设计目标是为了让后端或 API 独立于服务器验证用户
|
||||
|
||||
!!! info "说明"
|
||||
|
||||
`Beare` 令牌不是唯一的选择。
|
||||
`Bearer` 令牌不是唯一的选择。
|
||||
|
||||
但它是最适合这个用例的方案。
|
||||
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
# 使用(哈希)密码和 JWT Bearer 令牌的 OAuth2
|
||||
# OAuth2 实现密码哈希与 Bearer JWT 令牌验证
|
||||
|
||||
既然我们已经有了所有的安全流程,就让我们来使用 <abbr title="JSON Web Tokens">JWT</abbr> 令牌和安全哈希密码让应用程序真正地安全吧。
|
||||
至此,我们已经编写了所有安全流,本章学习如何使用 <abbr title="JSON Web Tokens">JWT</abbr> 令牌(Token)和安全密码哈希(Hash)实现真正的安全机制。
|
||||
|
||||
你可以在应用程序中真正地使用这些代码,在数据库中保存密码哈希值,等等。
|
||||
本章的示例代码真正实现了在应用的数据库中保存哈希密码等功能。
|
||||
|
||||
我们将从上一章结束的位置开始,然后对示例进行扩充。
|
||||
接下来,我们紧接上一章,继续完善安全机制。
|
||||
|
||||
## 关于 JWT
|
||||
## JWT 简介
|
||||
|
||||
JWT 表示 「JSON Web Tokens」。
|
||||
JWT 即**JSON 网络令牌**(JSON Web Tokens)。
|
||||
|
||||
它是一个将 JSON 对象编码为密集且没有空格的长字符串的标准。字符串看起来像这样:
|
||||
JWT 是一种将 JSON 对象编码为没有空格,且难以理解的长字符串的标准。JWT 的内容如下所示:
|
||||
|
||||
```
|
||||
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
|
||||
```
|
||||
|
||||
它没有被加密,因此任何人都可以从字符串内容中还原数据。
|
||||
JWT 字符串没有加密,任何人都能用它恢复原始信息。
|
||||
|
||||
但它经过了签名。因此,当你收到一个由你发出的令牌时,可以校验令牌是否真的由你发出。
|
||||
但 JWT 使用了签名机制。接受令牌时,可以用签名校验令牌。
|
||||
|
||||
通过这种方式,你可以创建一个有效期为 1 周的令牌。然后当用户第二天使用令牌重新访问时,你知道该用户仍然处于登入状态。
|
||||
使用 JWT 创建有效期为一周的令牌。第二天,用户持令牌再次访问时,仍为登录状态。
|
||||
|
||||
一周后令牌将会过期,用户将不会通过认证,必须再次登录才能获得一个新令牌。而且如果用户(或第三方)试图修改令牌以篡改过期时间,你将因为签名不匹配而能够发觉。
|
||||
令牌于一周后过期,届时,用户身份验证就会失败。只有再次登录,才能获得新的令牌。如果用户(或第三方)篡改令牌的过期时间,因为签名不匹配会导致身份验证失败。
|
||||
|
||||
如果你想上手体验 JWT 令牌并了解其工作方式,可访问 <a href="https://jwt.io/" class="external-link" target="_blank">https://jwt.io</a>。
|
||||
如需深入了解 JWT 令牌,了解它的工作方式,请参阅 <a href="https://jwt.io/" class="external-link" target="_blank">https://jwt.io</a>。
|
||||
|
||||
## 安装 `python-jose`
|
||||
|
||||
我们需要安装 `python-jose` 以在 Python 中生成和校验 JWT 令牌:
|
||||
安装 `python-jose`,在 Python 中生成和校验 JWT 令牌:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
@@ -40,38 +40,39 @@ $ pip install python-jose[cryptography]
|
||||
|
||||
</div>
|
||||
|
||||
<a href="https://github.com/mpdavis/python-jose" class="external-link" target="_blank">Python-jose</a> 需要一个额外的加密后端。
|
||||
<a href="https://github.com/mpdavis/python-jose" class="external-link" target="_blank">Python-jose</a> 需要安装配套的加密后端。
|
||||
|
||||
这里我们使用的是推荐的后端:<a href="https://cryptography.io/" class="external-link" target="_blank">pyca/cryptography</a>。
|
||||
本教程推荐的后端是:<a href="https://cryptography.io/" class="external-link" target="_blank">pyca/cryptography</a>。
|
||||
|
||||
!!! tip
|
||||
本教程曾经使用过 <a href="https://pyjwt.readthedocs.io/" class="external-link" target="_blank">PyJWT</a>。
|
||||
!!! tip "提示"
|
||||
|
||||
但是后来更新为使用 Python-jose,因为它提供了 PyJWT 的所有功能,以及之后与其他工具进行集成时你可能需要的一些其他功能。
|
||||
本教程以前使用 <a href="https://pyjwt.readthedocs.io/" class="external-link" target="_blank">PyJWT</a>。
|
||||
|
||||
## 哈希密码
|
||||
但后来换成了 Python-jose,因为 Python-jose 支持 PyJWT 的所有功能,还支持与其它工具集成时可能会用到的一些其它功能。
|
||||
|
||||
「哈希」的意思是:将某些内容(在本例中为密码)转换为看起来像乱码的字节序列(只是一个字符串)。
|
||||
## 密码哈希
|
||||
|
||||
每次你传入完全相同的内容(完全相同的密码)时,你都会得到完全相同的乱码。
|
||||
**哈希**是指把特定内容(本例中为密码)转换为乱码形式的字节序列(其实就是字符串)。
|
||||
|
||||
但是你不能从乱码转换回密码。
|
||||
每次传入完全相同的内容时(比如,完全相同的密码),返回的都是完全相同的乱码。
|
||||
|
||||
### 为什么使用哈希密码
|
||||
但这个乱码无法转换回传入的密码。
|
||||
|
||||
如果你的数据库被盗,小偷将无法获得用户的明文密码,只能拿到哈希值。
|
||||
### 为什么使用密码哈希
|
||||
|
||||
因此,小偷将无法尝试在另一个系统中使用这些相同的密码(由于许多用户在任何地方都使用相同的密码,因此这很危险)。
|
||||
原因很简单,假如数据库被盗,窃贼无法获取用户的明文密码,得到的只是哈希值。
|
||||
|
||||
这样一来,窃贼就无法在其它应用中使用窃取的密码,要知道,很多用户在所有系统中都使用相同的密码,风险超大)。
|
||||
|
||||
## 安装 `passlib`
|
||||
|
||||
PassLib 是一个用于处理哈希密码的很棒的 Python 包。
|
||||
Passlib 是处理密码哈希的 Python 包。
|
||||
|
||||
它支持许多安全哈希算法以及配合算法使用的实用程序。
|
||||
它支持很多安全哈希算法及配套工具。
|
||||
|
||||
推荐的算法是 「Bcrypt」。
|
||||
本教程推荐的算法是 **Bcrypt**。
|
||||
|
||||
因此,安装附带 Bcrypt 的 PassLib:
|
||||
因此,请先安装附带 Bcrypt 的 PassLib:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
@@ -83,46 +84,49 @@ $ pip install passlib[bcrypt]
|
||||
|
||||
</div>
|
||||
|
||||
!!! tip
|
||||
使用 `passlib`,你甚至可以将其配置为能够读取 Django,Flask 的安全扩展或许多其他工具创建的密码。
|
||||
!!! tip "提示"
|
||||
|
||||
因此,你将能够,举个例子,将数据库中来自 Django 应用的数据共享给一个 FastAPI 应用。或者使用同一数据库但逐渐将应用从 Django 迁移到 FastAPI。
|
||||
`passlib` 甚至可以读取 Django、Flask 的安全插件等工具创建的密码。
|
||||
|
||||
而你的用户将能够同时从 Django 应用或 FastAPI 应用登录。
|
||||
例如,把 Django 应用的数据共享给 FastAPI 应用的数据库。或利用同一个数据库,可以逐步把应用从 Django 迁移到 FastAPI。
|
||||
|
||||
## 哈希并校验密码
|
||||
并且,用户可以同时从 Django 应用或 FastAPI 应用登录。
|
||||
|
||||
从 `passlib` 导入我们需要的工具。
|
||||
## 密码哈希与校验
|
||||
|
||||
创建一个 PassLib 「上下文」。这将用于哈希和校验密码。
|
||||
从 `passlib` 导入所需工具。
|
||||
|
||||
!!! tip
|
||||
PassLib 上下文还具有使用不同哈希算法的功能,包括仅允许用于校验的已弃用的旧算法等。
|
||||
创建用于密码哈希和身份校验的 PassLib **上下文**。
|
||||
|
||||
例如,你可以使用它来读取和校验由另一个系统(例如Django)生成的密码,但是使用其他算法例如 Bcrypt 生成新的密码哈希值。
|
||||
!!! tip "提示"
|
||||
|
||||
并同时兼容所有的这些功能。
|
||||
PassLib 上下文还支持使用不同哈希算法的功能,包括只能校验的已弃用旧算法等。
|
||||
|
||||
创建一个工具函数以哈希来自用户的密码。
|
||||
例如,用它读取和校验其它系统(如 Django)生成的密码,但要使用其它算法,如 Bcrypt,生成新的哈希密码。
|
||||
|
||||
然后创建另一个工具函数,用于校验接收的密码是否与存储的哈希值匹配。
|
||||
同时,这些功能都是兼容的。
|
||||
|
||||
再创建另一个工具函数用于认证并返回用户。
|
||||
接下来,创建三个工具函数,其中一个函数用于哈希用户的密码。
|
||||
|
||||
第一个函数用于校验接收的密码是否匹配存储的哈希值。
|
||||
|
||||
第三个函数用于身份验证,并返回用户。
|
||||
|
||||
```Python hl_lines="7 48 55-56 59-60 69-75"
|
||||
{!../../../docs_src/security/tutorial004.py!}
|
||||
```
|
||||
|
||||
!!! note
|
||||
如果你查看新的(伪)数据库 `fake_users_db`,你将看到哈希后的密码现在的样子:`"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`。
|
||||
!!! note "笔记"
|
||||
|
||||
查看新的(伪)数据库 `fake_users_db`,就能看到哈希后的密码:`"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`。
|
||||
|
||||
## 处理 JWT 令牌
|
||||
|
||||
导入已安装的模块。
|
||||
|
||||
创建一个随机密钥,该密钥将用于对 JWT 令牌进行签名。
|
||||
创建用于 JWT 令牌签名的随机密钥。
|
||||
|
||||
要生成一个安全的随机密钥,可使用以下命令:
|
||||
使用以下命令,生成安全的随机密钥:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
@@ -134,15 +138,15 @@ $ openssl rand -hex 32
|
||||
|
||||
</div>
|
||||
|
||||
然后将输出复制到变量 「SECRET_KEY」 中(不要使用示例中的这个)。
|
||||
然后,把生成的密钥复制到变量**SECRET_KEY**,注意,不要使用本例所示的密钥。
|
||||
|
||||
创建用于设定 JWT 令牌签名算法的变量 「ALGORITHM」,并将其设置为 `"HS256"`。
|
||||
创建指定 JWT 令牌签名算法的变量 **ALGORITHM**,本例中的值为 `"HS256"`。
|
||||
|
||||
创建一个设置令牌过期时间的变量。
|
||||
创建设置令牌过期时间的变量。
|
||||
|
||||
定义一个将在令牌端点中用于响应的 Pydantic 模型。
|
||||
定义令牌端点响应的 Pydantic 模型。
|
||||
|
||||
创建一个生成新的访问令牌的工具函数。
|
||||
创建生成新的访问令牌的工具函数。
|
||||
|
||||
```Python hl_lines="6 12-14 28-30 78-86"
|
||||
{!../../../docs_src/security/tutorial004.py!}
|
||||
@@ -150,11 +154,11 @@ $ openssl rand -hex 32
|
||||
|
||||
## 更新依赖项
|
||||
|
||||
更新 `get_current_user` 以接收与之前相同的令牌,但这次使用的是 JWT 令牌。
|
||||
更新 `get_current_user` 以接收与之前相同的令牌,但这里用的是 JWT 令牌。
|
||||
|
||||
解码接收到的令牌,对其进行校验,然后返回当前用户。
|
||||
解码并校验接收到的令牌,然后,返回当前用户。
|
||||
|
||||
如果令牌无效,立即返回一个 HTTP 错误。
|
||||
如果令牌无效,则直接返回 HTTP 错误。
|
||||
|
||||
```Python hl_lines="89-106"
|
||||
{!../../../docs_src/security/tutorial004.py!}
|
||||
@@ -162,57 +166,57 @@ $ openssl rand -hex 32
|
||||
|
||||
## 更新 `/token` *路径操作*
|
||||
|
||||
使用令牌的过期时间创建一个 `timedelta` 对象。
|
||||
用令牌过期时间创建 `timedelta` 对象。
|
||||
|
||||
创建一个真实的 JWT 访问令牌并返回它。
|
||||
创建并返回真正的 JWT 访问令牌。
|
||||
|
||||
```Python hl_lines="115-128"
|
||||
{!../../../docs_src/security/tutorial004.py!}
|
||||
```
|
||||
|
||||
### 关于 JWT 「主题」 `sub` 的技术细节
|
||||
### JWT `sub` 的技术细节
|
||||
|
||||
JWT 的规范中提到有一个 `sub` 键,值为该令牌的主题。
|
||||
JWT 规范还包括 `sub` 键,值是令牌的主题。
|
||||
|
||||
使用它并不是必须的,但这是你放置用户标识的地方,所以我们在示例中使用了它。
|
||||
该键是可选的,但要把用户标识放在这个键里,所以本例使用了该键。
|
||||
|
||||
除了识别用户并允许他们直接在你的 API 上执行操作之外,JWT 还可以用于其他事情。
|
||||
除了识别用户与许可用户在 API 上直接执行操作之外,JWT 还可能用于其它事情。
|
||||
|
||||
例如,你可以识别一个 「汽车」 或 「博客文章」。
|
||||
例如,识别**汽车**或**博客**。
|
||||
|
||||
然后你可以添加关于该实体的权限,比如「驾驶」(汽车)或「编辑」(博客)。
|
||||
接着,为实体添加权限,比如**驾驶**(汽车)或**编辑**(博客)。
|
||||
|
||||
然后,你可以将 JWT 令牌交给用户(或机器人),他们可以使用它来执行这些操作(驾驶汽车,或编辑博客文章),甚至不需要有一个账户,只需使用你的 API 为其生成的 JWT 令牌。
|
||||
然后,把 JWT 令牌交给用户(或机器人),他们就可以执行驾驶汽车,或编辑博客等操作。无需注册账户,只要有 API 生成的 JWT 令牌就可以。
|
||||
|
||||
使用这样的思路,JWT 可以用于更复杂的场景。
|
||||
同理,JWT 可以用于更复杂的场景。
|
||||
|
||||
在这些情况下,几个实体可能有相同的 ID,比如说 `foo`(一个用户 `foo`,一辆车 `foo`,一篇博客文章 `foo`)。
|
||||
在这些情况下,多个实体的 ID 可能是相同的,以 ID `foo` 为例,用户的 ID 是 `foo`,车的 ID 是 `foo`,博客的 ID 也是 `foo`。
|
||||
|
||||
因此,为了避免 ID 冲突,当为用户创建 JWT 令牌时,你可以在 `sub` 键的值前加上前缀,例如 `username:`。所以,在这个例子中,`sub` 的值可以是:`username:johndoe`。
|
||||
为了避免 ID 冲突,在给用户创建 JWT 令牌时,可以为 `sub` 键的值加上前缀,例如 `username:`。因此,在本例中,`sub` 的值可以是:`username:johndoe`。
|
||||
|
||||
要记住的重点是,`sub` 键在整个应用程序中应该有一个唯一的标识符,而且应该是一个字符串。
|
||||
注意,划重点,`sub` 键在整个应用中应该只有一个唯一的标识符,而且应该是字符串。
|
||||
|
||||
## 检查效果
|
||||
## 检查
|
||||
|
||||
运行服务器并访问文档: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>。
|
||||
|
||||
你会看到如下用户界面:
|
||||
可以看到如下用户界面:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/security/image07.png">
|
||||
|
||||
像以前一样对应用程序进行认证。
|
||||
用与上一章同样的方式实现应用授权。
|
||||
|
||||
使用如下凭证:
|
||||
|
||||
用户名: `johndoe`
|
||||
密码: `secret`
|
||||
用户名: `johndoe` 密码: `secret`
|
||||
|
||||
!!! check
|
||||
请注意,代码中没有任何地方记录了明文密码 「`secret`」,我们只保存了其哈希值。
|
||||
!!! check "检查"
|
||||
|
||||
注意,代码中没有明文密码**`secret`**,只保存了它的哈希值。
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/security/image08.png">
|
||||
|
||||
访问 `/users/me/` 端点,你将获得如下响应:
|
||||
调用 `/users/me/` 端点,收到下面的响应:
|
||||
|
||||
```JSON
|
||||
{
|
||||
@@ -225,41 +229,42 @@ JWT 的规范中提到有一个 `sub` 键,值为该令牌的主题。
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/security/image09.png">
|
||||
|
||||
如果你打开开发者工具,将看到数据是如何发送的并且其中仅包含了令牌,只有在第一个请求中发送了密码以校验用户身份并获取该访问令牌,但之后都不会再发送密码:
|
||||
打开浏览器的开发者工具,查看数据是怎么发送的,而且数据里只包含了令牌,只有验证用户的第一个请求才发送密码,并获取访问令牌,但之后不会再发送密码:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/security/image10.png">
|
||||
|
||||
!!! note
|
||||
注意请求中的 `Authorization` 首部,其值以 `Bearer` 开头。
|
||||
!!! note "笔记"
|
||||
|
||||
## 使用 `scopes` 的进阶用法
|
||||
注意,请求中 `Authorization` 响应头的值以 `Bearer` 开头。
|
||||
|
||||
OAuth2 具有「作用域」的概念。
|
||||
## `scopes` 高级用法
|
||||
|
||||
你可以使用它们向 JWT 令牌添加一组特定的权限。
|
||||
OAuth2 支持**`scopes`**(作用域)。
|
||||
|
||||
然后,你可以将此令牌直接提供给用户或第三方,使其在一些限制下与你的 API 进行交互。
|
||||
**`scopes`**为 JWT 令牌添加指定权限。
|
||||
|
||||
你可以在之后的**进阶用户指南**中了解如何使用它们以及如何将它们集成到 **FastAPI** 中。
|
||||
让持有令牌的用户或第三方在指定限制条件下与 API 交互。
|
||||
|
||||
## 总结
|
||||
**高级用户指南**中将介绍如何使用 `scopes`,及如何把 `scopes` 集成至 **FastAPI**。
|
||||
|
||||
通过目前你所看到的,你可以使用像 OAuth2 和 JWT 这样的标准来构建一个安全的 **FastAPI** 应用程序。
|
||||
## 小结
|
||||
|
||||
在几乎所有的框架中,处理安全性问题都很容易成为一个相当复杂的话题。
|
||||
至此,您可以使用 OAuth2 和 JWT 等标准配置安全的 **FastAPI** 应用。
|
||||
|
||||
许多高度简化了安全流程的软件包不得不在数据模型、数据库和可用功能上做出很多妥协。而这些过于简化流程的软件包中,有些其实隐含了安全漏洞。
|
||||
几乎在所有框架中,处理安全问题很快都会变得非常复杂。
|
||||
|
||||
有些包为了简化安全流,不得不在数据模型、数据库和功能上做出妥协。而有些过于简化的软件包其实存在了安全隐患。
|
||||
|
||||
---
|
||||
|
||||
**FastAPI** 不对任何数据库、数据模型或工具做任何妥协。
|
||||
**FastAPI** 不向任何数据库、数据模型或工具做妥协。
|
||||
|
||||
它给了你所有的灵活性来选择最适合你项目的前者。
|
||||
开发者可以灵活选择最适合项目的安全机制。
|
||||
|
||||
你可以直接使用许多维护良好且使用广泛的包,如 `passlib` 和 `python-jose`,因为 **FastAPI** 不需要任何复杂的机制来集成外部包。
|
||||
还可以直接使用 `passlib` 和 `python-jose` 等维护良好、使用广泛的包,这是因为 **FastAPI** 不需要任何复杂机制,就能集成外部的包。
|
||||
|
||||
但它为你提供了一些工具,在不影响灵活性、健壮性和安全性的前提下,尽可能地简化这个过程。
|
||||
而且,**FastAPI** 还提供了一些工具,在不影响灵活、稳定和安全的前提下,尽可能地简化安全机制。
|
||||
|
||||
而且你可以用相对简单的方式使用和实现安全、标准的协议,比如 OAuth2。
|
||||
**FastAPI** 还支持以相对简单的方式,使用 OAuth2 等安全、标准的协议。
|
||||
|
||||
你可以在**进阶用户指南**中了解更多关于如何使用 OAuth2 「作用域」的信息,以实现更精细的权限系统,并同样遵循这些标准。带有作用域的 OAuth2 是很多大的认证提供商使用的机制,比如 Facebook、Google、GitHub、微软、Twitter 等,授权第三方应用代表用户与他们的 API 进行交互。
|
||||
**高级用户指南**中详细介绍了 OAuth2**`scopes`**的内容,遵循同样的标准,实现更精密的权限系统。OAuth2 的作用域是脸书、谷歌、GitHub、微软、推特等第三方身份验证应用使用的机制,让用户授权第三方应用与 API 交互。
|
||||
|
||||
770
docs/zh/docs/tutorial/sql-databases.md
Normal file
770
docs/zh/docs/tutorial/sql-databases.md
Normal file
@@ -0,0 +1,770 @@
|
||||
# SQL (关系型) 数据库
|
||||
|
||||
**FastAPI**不需要你使用SQL(关系型)数据库。
|
||||
|
||||
但是您可以使用任何您想要的关系型数据库。
|
||||
|
||||
在这里,让我们看一个使用着[SQLAlchemy](https://www.sqlalchemy.org/)的示例。
|
||||
|
||||
您可以很容易地将SQLAlchemy支持任何数据库,像:
|
||||
|
||||
* PostgreSQL
|
||||
* MySQL
|
||||
* SQLite
|
||||
* Oracle
|
||||
* Microsoft SQL Server,等等其它数据库
|
||||
|
||||
在此示例中,我们将使用**SQLite**,因为它使用单个文件并且 在Python中具有集成支持。因此,您可以复制此示例并按原样来运行它。
|
||||
|
||||
稍后,对于您的产品级别的应用程序,您可能会要使用像**PostgreSQL**这样的数据库服务器。
|
||||
|
||||
!!! tip
|
||||
这儿有一个**FastAPI**和**PostgreSQL**的官方项目生成器,全部基于**Docker**,包括前端和更多工具:<a href="https://github.com/tiangolo/full-stack-fastapi-postgresql" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-fastapi-postgresql</a>
|
||||
|
||||
!!! note
|
||||
请注意,大部分代码是`SQLAlchemy`的标准代码,您可以用于任何框架。FastAPI特定的代码和往常一样少。
|
||||
|
||||
## ORMs(对象关系映射)
|
||||
|
||||
**FastAPI**可与任何数据库在任何样式的库中一起与 数据库进行通信。
|
||||
|
||||
一种常见的模式是使用“ORM”:对象关系映射。
|
||||
|
||||
ORM 具有在代码和数据库表(“*关系型”)中的**对象**之间转换(“*映射*”)的工具。
|
||||
|
||||
使用 ORM,您通常会在 SQL 数据库中创建一个代表映射的类,该类的每个属性代表一个列,具有名称和类型。
|
||||
|
||||
例如,一个类`Pet`可以表示一个 SQL 表`pets`。
|
||||
|
||||
该类的每个*实例对象都代表数据库中的一行数据。*
|
||||
|
||||
又例如,一个对象`orion_cat`(`Pet`的一个实例)可以有一个属性`orion_cat.type`, 对标数据库中的`type`列。并且该属性的值可以是其它,例如`"cat"`。
|
||||
|
||||
这些 ORM 还具有在表或实体之间建立关系的工具(比如创建多表关系)。
|
||||
|
||||
这样,您还可以拥有一个属性`orion_cat.owner`,它包含该宠物所有者的数据,这些数据取自另外一个表。
|
||||
|
||||
因此,`orion_cat.owner.name`可能是该宠物主人的姓名(来自表`owners`中的列`name`)。
|
||||
|
||||
它可能有一个像`"Arquilian"`(一种业务逻辑)。
|
||||
|
||||
当您尝试从您的宠物对象访问它时,ORM 将完成所有工作以从相应的表*所有者那里再获取信息。*
|
||||
|
||||
常见的 ORM 例如:Django-ORM(Django 框架的一部分)、SQLAlchemy ORM(SQLAlchemy 的一部分,独立于框架)和 Peewee(独立于框架)等。
|
||||
|
||||
在这里,我们将看到如何使用**SQLAlchemy ORM**。
|
||||
|
||||
以类似的方式,您也可以使用任何其他 ORM。
|
||||
|
||||
!!! tip
|
||||
在文档中也有一篇使用 Peewee 的等效的文章。
|
||||
|
||||
## 文件结构
|
||||
|
||||
对于这些示例,假设您有一个名为的目录`my_super_project`,其中包含一个名为的子目录`sql_app`,其结构如下:
|
||||
|
||||
```
|
||||
.
|
||||
└── sql_app
|
||||
├── __init__.py
|
||||
├── crud.py
|
||||
├── database.py
|
||||
├── main.py
|
||||
├── models.py
|
||||
└── schemas.py
|
||||
```
|
||||
|
||||
该文件`__init__.py`只是一个空文件,但它告诉 Python 其中`sql_app`的所有模块(Python 文件)都是一个包。
|
||||
|
||||
现在让我们看看每个文件/模块的作用。
|
||||
|
||||
## 创建 SQLAlchemy 部件
|
||||
|
||||
让我们涉及到文件`sql_app/database.py`。
|
||||
|
||||
### 导入 SQLAlchemy 部件
|
||||
|
||||
```Python hl_lines="1-3"
|
||||
{!../../../docs_src/sql_databases/sql_app/database.py!}
|
||||
```
|
||||
|
||||
### 为 SQLAlchemy 定义数据库 URL地址
|
||||
|
||||
```Python hl_lines="5-6"
|
||||
{!../../../docs_src/sql_databases/sql_app/database.py!}
|
||||
```
|
||||
|
||||
在这个例子中,我们正在“连接”到一个 SQLite 数据库(用 SQLite 数据库打开一个文件)。
|
||||
|
||||
该文件将位于文件中的同一目录中`sql_app.db`。
|
||||
|
||||
这就是为什么最后一部分是`./sql_app.db`.
|
||||
|
||||
如果您使用的是**PostgreSQL**数据库,则只需取消注释该行:
|
||||
|
||||
```Python
|
||||
SQLALCHEMY_DATABASE_URL = "postgresql://user:password@postgresserver/db"
|
||||
```
|
||||
|
||||
...并根据您的数据库数据和相关凭据(也适用于 MySQL、MariaDB 或任何其他)对其进行调整。
|
||||
|
||||
!!! tip
|
||||
|
||||
如果您想使用不同的数据库,这是就是您必须修改的地方。
|
||||
|
||||
### 创建 SQLAlchemy 引擎
|
||||
|
||||
第一步,创建一个 SQLAlchemy的“引擎”。
|
||||
|
||||
我们稍后会将这个`engine`在其他地方使用。
|
||||
|
||||
```Python hl_lines="8-10"
|
||||
{!../../../docs_src/sql_databases/sql_app/database.py!}
|
||||
```
|
||||
|
||||
#### 注意
|
||||
|
||||
参数:
|
||||
|
||||
```Python
|
||||
connect_args={"check_same_thread": False}
|
||||
```
|
||||
|
||||
...仅用于`SQLite`,在其他数据库不需要它。
|
||||
|
||||
!!! info "技术细节"
|
||||
|
||||
默认情况下,SQLite 只允许一个线程与其通信,假设有多个线程的话,也只将处理一个独立的请求。
|
||||
|
||||
这是为了防止意外地为不同的事物(不同的请求)共享相同的连接。
|
||||
|
||||
但是在 FastAPI 中,普遍使用def函数,多个线程可以为同一个请求与数据库交互,所以我们需要使用`connect_args={"check_same_thread": False}`来让SQLite允许这样。
|
||||
|
||||
此外,我们将确保每个请求都在依赖项中获得自己的数据库连接会话,因此不需要该默认机制。
|
||||
|
||||
### 创建一个`SessionLocal`类
|
||||
|
||||
每个实例`SessionLocal`都会是一个数据库会话。当然该类本身还不是数据库会话。
|
||||
|
||||
但是一旦我们创建了一个`SessionLocal`类的实例,这个实例将是实际的数据库会话。
|
||||
|
||||
我们命名它是`SessionLocal`为了将它与我们从 SQLAlchemy 导入的`Session`区别开来。
|
||||
|
||||
稍后我们将使用`Session`(从 SQLAlchemy 导入的那个)。
|
||||
|
||||
要创建`SessionLocal`类,请使用函数`sessionmaker`:
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!../../../docs_src/sql_databases/sql_app/database.py!}
|
||||
```
|
||||
|
||||
### 创建一个`Base`类
|
||||
|
||||
现在我们将使用`declarative_base()`返回一个类。
|
||||
|
||||
稍后我们将用这个类继承,来创建每个数据库模型或类(ORM 模型):
|
||||
|
||||
```Python hl_lines="13"
|
||||
{!../../../docs_src/sql_databases/sql_app/database.py!}
|
||||
```
|
||||
|
||||
## 创建数据库模型
|
||||
|
||||
现在让我们看看文件`sql_app/models.py`。
|
||||
|
||||
### 用`Base`类来创建 SQLAlchemy 模型
|
||||
|
||||
我们将使用我们之前创建的`Base`类来创建 SQLAlchemy 模型。
|
||||
|
||||
!!! tip
|
||||
SQLAlchemy 使用的“**模型**”这个术语 来指代与数据库交互的这些类和实例。
|
||||
|
||||
而 Pydantic 也使用“模型”这个术语 来指代不同的东西,即数据验证、转换以及文档类和实例。
|
||||
|
||||
从`database`(来自上面的`database.py`文件)导入`Base`。
|
||||
|
||||
创建从它继承的类。
|
||||
|
||||
这些类就是 SQLAlchemy 模型。
|
||||
|
||||
```Python hl_lines="4 7-8 18-19"
|
||||
{!../../../docs_src/sql_databases/sql_app/models.py!}
|
||||
```
|
||||
|
||||
这个`__tablename__`属性是用来告诉 SQLAlchemy 要在数据库中为每个模型使用的数据库表的名称。
|
||||
|
||||
### 创建模型属性/列
|
||||
|
||||
现在创建所有模型(类)属性。
|
||||
|
||||
这些属性中的每一个都代表其相应数据库表中的一列。
|
||||
|
||||
我们使用`Column`来表示 SQLAlchemy 中的默认值。
|
||||
|
||||
我们传递一个 SQLAlchemy “类型”,如`Integer`、`String`和`Boolean`,它定义了数据库中的类型,作为参数。
|
||||
|
||||
```Python hl_lines="1 10-13 21-24"
|
||||
{!../../../docs_src/sql_databases/sql_app/models.py!}
|
||||
```
|
||||
|
||||
### 创建关系
|
||||
|
||||
现在创建关系。
|
||||
|
||||
为此,我们使用SQLAlchemy ORM提供的`relationship`。
|
||||
|
||||
这将或多或少会成为一种“神奇”属性,其中表示该表与其他相关的表中的值。
|
||||
|
||||
```Python hl_lines="2 15 26"
|
||||
{!../../../docs_src/sql_databases/sql_app/models.py!}
|
||||
```
|
||||
|
||||
当访问 user 中的属性`items`时,如 中`my_user.items`,它将有一个`Item`SQLAlchemy 模型列表(来自`items`表),这些模型具有指向`users`表中此记录的外键。
|
||||
|
||||
当您访问`my_user.items`时,SQLAlchemy 实际上会从`items`表中的获取一批记录并在此处填充进去。
|
||||
|
||||
同样,当访问 Item中的属性`owner`时,它将包含表中的`User`SQLAlchemy 模型`users`。使用`owner_id`属性/列及其外键来了解要从`users`表中获取哪条记录。
|
||||
|
||||
## 创建 Pydantic 模型
|
||||
|
||||
现在让我们查看一下文件`sql_app/schemas.py`。
|
||||
|
||||
!!! tip
|
||||
为了避免 SQLAlchemy*模型*和 Pydantic*模型*之间的混淆,我们将有`models.py`(SQLAlchemy 模型的文件)和`schemas.py`( Pydantic 模型的文件)。
|
||||
|
||||
这些 Pydantic 模型或多或少地定义了一个“schema”(一个有效的数据形状)。
|
||||
|
||||
因此,这将帮助我们在使用两者时避免混淆。
|
||||
|
||||
### 创建初始 Pydantic*模型*/模式
|
||||
|
||||
创建一个`ItemBase`和`UserBase`Pydantic*模型*(或者我们说“schema”)以及在创建或读取数据时具有共同的属性。
|
||||
|
||||
`ItemCreate`为 创建一个`UserCreate`继承自它们的所有属性(因此它们将具有相同的属性),以及创建所需的任何其他数据(属性)。
|
||||
|
||||
因此在创建时也应当有一个`password`属性。
|
||||
|
||||
但是为了安全起见,`password`不会出现在其他同类 Pydantic*模型*中,例如用户请求时不应该从 API 返回响应中包含它。
|
||||
|
||||
=== "Python 3.6 及以上版本"
|
||||
|
||||
```Python hl_lines="3 6-8 11-12 23-24 27-28"
|
||||
{!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 及以上版本"
|
||||
|
||||
```Python hl_lines="3 6-8 11-12 23-24 27-28"
|
||||
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 及以上版本"
|
||||
|
||||
```Python hl_lines="1 4-6 9-10 21-22 25-26"
|
||||
{!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
|
||||
```
|
||||
|
||||
#### SQLAlchemy 风格和 Pydantic 风格
|
||||
|
||||
请注意,SQLAlchemy*模型*使用 `=`来定义属性,并将类型作为参数传递给`Column`,例如:
|
||||
|
||||
```Python
|
||||
name = Column(String)
|
||||
```
|
||||
|
||||
虽然 Pydantic*模型*使用`:` 声明类型,但新的类型注释语法/类型提示是:
|
||||
|
||||
```Python
|
||||
name: str
|
||||
```
|
||||
|
||||
请牢记这一点,这样您在使用`:`还是`=`时就不会感到困惑。
|
||||
|
||||
### 创建用于读取/返回的Pydantic*模型/模式*
|
||||
|
||||
现在创建当从 API 返回数据时、将在读取数据时使用的Pydantic*模型(schemas)。*
|
||||
|
||||
例如,在创建一个项目之前,我们不知道分配给它的 ID 是什么,但是在读取它时(从 API 返回时)我们已经知道它的 ID。
|
||||
|
||||
同样,当读取用户时,我们现在可以声明`items`,将包含属于该用户的项目。
|
||||
|
||||
不仅是这些项目的 ID,还有我们在 Pydantic*模型*中定义的用于读取项目的所有数据:`Item`.
|
||||
|
||||
=== "Python 3.6 及以上版本"
|
||||
|
||||
```Python hl_lines="15-17 31-34"
|
||||
{!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 及以上版本"
|
||||
|
||||
```Python hl_lines="15-17 31-34"
|
||||
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 及以上版本"
|
||||
|
||||
```Python hl_lines="13-15 29-32"
|
||||
{!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
请注意,读取用户(从 API 返回)时将使用不包括`password`的`User` Pydantic*模型*。
|
||||
|
||||
### 使用 Pydantic 的`orm_mode`
|
||||
|
||||
现在,在用于查询的 Pydantic*模型*`Item`中`User`,添加一个内部`Config`类。
|
||||
|
||||
此类[`Config`](https://pydantic-docs.helpmanual.io/usage/model_config/)用于为 Pydantic 提供配置。
|
||||
|
||||
在`Config`类中,设置属性`orm_mode = True`。
|
||||
|
||||
=== "Python 3.6 及以上版本"
|
||||
|
||||
```Python hl_lines="15 19-20 31 36-37"
|
||||
{!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 及以上版本"
|
||||
|
||||
```Python hl_lines="15 19-20 31 36-37"
|
||||
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 及以上版本"
|
||||
|
||||
```Python hl_lines="13 17-18 29 34-35"
|
||||
{!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
请注意,它使用`=`分配一个值,例如:
|
||||
|
||||
`orm_mode = True`
|
||||
|
||||
它不使用之前的`:`来类型声明。
|
||||
|
||||
这是设置配置值,而不是声明类型。
|
||||
|
||||
Pydantic`orm_mode`将告诉 Pydantic*模型*读取数据,即它不是一个`dict`,而是一个 ORM 模型(或任何其他具有属性的任意对象)。
|
||||
|
||||
这样,而不是仅仅试图从`dict`上 `id` 中获取值,如下所示:
|
||||
|
||||
```Python
|
||||
id = data["id"]
|
||||
```
|
||||
|
||||
尝试从属性中获取它,如:
|
||||
|
||||
```Python
|
||||
id = data.id
|
||||
```
|
||||
|
||||
有了这个,Pydantic*模型*与 ORM 兼容,您只需在*路径操作*`response_model`的参数中声明它即可。
|
||||
|
||||
您将能够返回一个数据库模型,它将从中读取数据。
|
||||
|
||||
#### ORM 模式的技术细节
|
||||
|
||||
SQLAlchemy 和许多其他默认情况下是“延迟加载”。
|
||||
|
||||
这意味着,例如,除非您尝试访问包含该数据的属性,否则它们不会从数据库中获取关系数据。
|
||||
|
||||
例如,访问属性`items`:
|
||||
|
||||
```Python
|
||||
current_user.items
|
||||
```
|
||||
|
||||
将使 SQLAlchemy 转到`items`表并获取该用户的项目,在调用`.items`之前不会去查询数据库。
|
||||
|
||||
没有`orm_mode`,如果您从*路径操作*返回一个 SQLAlchemy 模型,它不会包含关系数据。
|
||||
|
||||
即使您在 Pydantic 模型中声明了这些关系,也没有用处。
|
||||
|
||||
但是在 ORM 模式下,由于 Pydantic 本身会尝试从属性访问它需要的数据(而不是假设为 `dict`),你可以声明你想要返回的特定数据,它甚至可以从 ORM 中获取它。
|
||||
|
||||
## CRUD工具
|
||||
|
||||
现在让我们看看文件`sql_app/crud.py`。
|
||||
|
||||
在这个文件中,我们将编写可重用的函数用来与数据库中的数据进行交互。
|
||||
|
||||
**CRUD**分别为:**增加**、**查询**、**更改**和**删除**,即增删改查。
|
||||
|
||||
...虽然在这个例子中我们只是新增和查询。
|
||||
|
||||
### 读取数据
|
||||
|
||||
从 `sqlalchemy.orm`中导入`Session`,这将允许您声明`db`参数的类型,并在您的函数中进行更好的类型检查和完成。
|
||||
|
||||
导入之前的`models`(SQLAlchemy 模型)和`schemas`(Pydantic*模型*/模式)。
|
||||
|
||||
创建一些实用函数来完成:
|
||||
|
||||
* 通过 ID 和电子邮件查询单个用户。
|
||||
* 查询多个用户。
|
||||
* 查询多个项目。
|
||||
|
||||
```Python hl_lines="1 3 6-7 10-11 14-15 27-28"
|
||||
{!../../../docs_src/sql_databases/sql_app/crud.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
通过创建仅专用于与数据库交互(获取用户或项目)的函数,独立于*路径操作函数*,您可以更轻松地在多个部分中重用它们,并为它们添加单元测试。
|
||||
|
||||
### 创建数据
|
||||
|
||||
现在创建实用程序函数来创建数据。
|
||||
|
||||
它的步骤是:
|
||||
|
||||
* 使用您的数据创建一个 SQLAlchemy 模型*实例。*
|
||||
* 使用`add`来将该实例对象添加到您的数据库。
|
||||
* 使用`commit`来对数据库的事务提交(以便保存它们)。
|
||||
* 使用`refresh`来刷新您的数据库实例(以便它包含来自数据库的任何新数据,例如生成的 ID)。
|
||||
|
||||
```Python hl_lines="18-24 31-36"
|
||||
{!../../../docs_src/sql_databases/sql_app/crud.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
SQLAlchemy 模型`User`包含一个`hashed_password`,它应该是一个包含散列的安全密码。
|
||||
|
||||
但由于 API 客户端提供的是原始密码,因此您需要将其提取并在应用程序中生成散列密码。
|
||||
|
||||
然后将hashed_password参数与要保存的值一起传递。
|
||||
|
||||
!!! warning
|
||||
此示例不安全,密码未经过哈希处理。
|
||||
|
||||
在现实生活中的应用程序中,您需要对密码进行哈希处理,并且永远不要以明文形式保存它们。
|
||||
|
||||
有关更多详细信息,请返回教程中的安全部分。
|
||||
|
||||
在这里,我们只关注数据库的工具和机制。
|
||||
|
||||
!!! tip
|
||||
这里不是将每个关键字参数传递给Item并从Pydantic模型中读取每个参数,而是先生成一个字典,其中包含Pydantic模型的数据:
|
||||
|
||||
`item.dict()`
|
||||
|
||||
然后我们将dict的键值对 作为关键字参数传递给 SQLAlchemy `Item`:
|
||||
|
||||
`Item(**item.dict())`
|
||||
|
||||
然后我们传递 Pydantic模型未提供的额外关键字参数`owner_id`:
|
||||
|
||||
`Item(**item.dict(), owner_id=user_id)`
|
||||
|
||||
## 主**FastAPI**应用程序
|
||||
|
||||
现在在`sql_app/main.py`文件中 让我们集成和使用我们之前创建的所有其他部分。
|
||||
|
||||
### 创建数据库表
|
||||
|
||||
以非常简单的方式创建数据库表:
|
||||
|
||||
=== "Python 3.6 及以上版本"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 及以上版本"
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
|
||||
```
|
||||
|
||||
#### Alembic 注意
|
||||
|
||||
通常你可能会使用 <a href="https://alembic.sqlalchemy.org/en/latest/" class="external-link" target="_blank">Alembic</a>,来进行格式化数据库(创建表等)。
|
||||
|
||||
而且您还可以将 Alembic 用于“迁移”(这是它的主要工作)。
|
||||
|
||||
“迁移”是每当您更改 SQLAlchemy 模型的结构、添加新属性等以在数据库中复制这些更改、添加新列、新表等时所需的一组步骤。
|
||||
|
||||
您可以在[Project Generation - Template](https://fastapi.tiangolo.com/zh/project-generation/)的模板中找到一个 FastAPI 项目中的 Alembic 示例。具体在[`alembic`代码目录中](https://github.com/tiangolo/full-stack-fastapi-postgresql/tree/master/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/alembic/)。
|
||||
|
||||
### 创建依赖项
|
||||
|
||||
现在使用我们在`sql_app/database.py`文件中创建的`SessionLocal`来创建依赖项。
|
||||
|
||||
我们需要每个请求有一个独立的数据库会话/连接(`SessionLocal`),在所有请求中使用相同的会话,然后在请求完成后关闭它。
|
||||
|
||||
然后将为下一个请求创建一个新会话。
|
||||
|
||||
为此,我们将创建一个新的依赖项`yield`,正如前面关于[Dependencies with`yield`](https://fastapi.tiangolo.com/zh/tutorial/dependencies/dependencies-with-yield/)的部分中所解释的那样。
|
||||
|
||||
我们的依赖项将创建一个新的 SQLAlchemy `SessionLocal`,它将在单个请求中使用,然后在请求完成后关闭它。
|
||||
|
||||
=== "Python 3.6 及以上版本"
|
||||
|
||||
```Python hl_lines="15-20"
|
||||
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 及以上版本"
|
||||
|
||||
```Python hl_lines="13-18"
|
||||
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
我们将`SessionLocal()`请求的创建和处理放在一个`try`块中。
|
||||
|
||||
然后我们在finally块中关闭它。
|
||||
|
||||
通过这种方式,我们确保数据库会话在请求后始终关闭。即使在处理请求时出现异常。
|
||||
|
||||
但是您不能从退出代码中引发另一个异常(在yield之后)。可以查阅 [Dependencies with yield and HTTPException](https://fastapi.tiangolo.com/zh/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-httpexception)
|
||||
|
||||
*然后,当在路径操作函数*中使用依赖项时,我们使用`Session`,直接从 SQLAlchemy 导入的类型声明它。
|
||||
|
||||
*这将为我们在路径操作函数*中提供更好的编辑器支持,因为编辑器将知道`db`参数的类型`Session`:
|
||||
|
||||
=== "Python 3.6 及以上版本"
|
||||
|
||||
```Python hl_lines="24 32 38 47 53"
|
||||
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 及以上版本"
|
||||
|
||||
```Python hl_lines="22 30 36 45 51"
|
||||
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
|
||||
```
|
||||
|
||||
!!! info "技术细节"
|
||||
参数`db`实际上是 type `SessionLocal`,但是这个类(用 创建`sessionmaker()`)是 SQLAlchemy 的“代理” `Session`,所以,编辑器并不真正知道提供了哪些方法。
|
||||
|
||||
但是通过将类型声明为Session,编辑器现在可以知道可用的方法(.add()、.query()、.commit()等)并且可以提供更好的支持(比如完成)。类型声明不影响实际对象。
|
||||
|
||||
### 创建您的**FastAPI** *路径操作*
|
||||
|
||||
现在,到了最后,编写标准的**FastAPI** *路径操作*代码。
|
||||
|
||||
=== "Python 3.6 及以上版本"
|
||||
|
||||
```Python hl_lines="23-28 31-34 37-42 45-49 52-55"
|
||||
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 及以上版本"
|
||||
|
||||
```Python hl_lines="21-26 29-32 35-40 43-47 50-53"
|
||||
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
|
||||
```
|
||||
|
||||
我们在依赖项中的每个请求之前利用`yield`创建数据库会话,然后关闭它。
|
||||
|
||||
所以我们就可以在*路径操作函数*中创建需要的依赖,就能直接获取会话。
|
||||
|
||||
这样,我们就可以直接从*路径操作函数*内部调用`crud.get_user`并使用该会话,来进行对数据库操作。
|
||||
|
||||
!!! tip
|
||||
请注意,您返回的值是 SQLAlchemy 模型或 SQLAlchemy 模型列表。
|
||||
|
||||
但是由于所有路径操作的response_model都使用 Pydantic模型/使用orm_mode模式,因此您的 Pydantic 模型中声明的数据将从它们中提取并返回给客户端,并进行所有正常的过滤和验证。
|
||||
|
||||
!!! tip
|
||||
另请注意,`response_models`应当是标准 Python 类型,例如`List[schemas.Item]`.
|
||||
|
||||
但是由于它的内容/参数List是一个 使用orm_mode模式的Pydantic模型,所以数据将被正常检索并返回给客户端,所以没有问题。
|
||||
|
||||
### 关于 `def` 对比 `async def`
|
||||
|
||||
*在这里,我们在路径操作函数*和依赖项中都使用着 SQLAlchemy 模型,它将与外部数据库进行通信。
|
||||
|
||||
这会需要一些“等待时间”。
|
||||
|
||||
但是由于 SQLAlchemy 不具有`await`直接使用的兼容性,因此类似于:
|
||||
|
||||
```Python
|
||||
user = await db.query(User).first()
|
||||
```
|
||||
|
||||
...相反,我们可以使用:
|
||||
|
||||
```Python
|
||||
user = db.query(User).first()
|
||||
```
|
||||
|
||||
然后我们应该声明*路径操作函数*和不带 的依赖关系`async def`,只需使用普通的`def`,如下:
|
||||
|
||||
```Python hl_lines="2"
|
||||
@app.get("/users/{user_id}", response_model=schemas.User)
|
||||
def read_user(user_id: int, db: Session = Depends(get_db)):
|
||||
db_user = crud.get_user(db, user_id=user_id)
|
||||
...
|
||||
```
|
||||
|
||||
!!! info
|
||||
如果您需要异步连接到关系数据库,请参阅[Async SQL (Relational) Databases](https://fastapi.tiangolo.com/zh/advanced/async-sql-databases/)
|
||||
|
||||
!!! note "Very Technical Details"
|
||||
如果您很好奇并且拥有深厚的技术知识,您可以在[Async](https://fastapi.tiangolo.com/zh/async/#very-technical-details)文档中查看有关如何处理 `async def`于`def`差别的技术细节。
|
||||
|
||||
## 迁移
|
||||
|
||||
因为我们直接使用 SQLAlchemy,并且我们不需要任何类型的插件来使用**FastAPI**,所以我们可以直接将数据库迁移至[Alembic](https://alembic.sqlalchemy.org/)进行集成。
|
||||
|
||||
由于与 SQLAlchemy 和 SQLAlchemy 模型相关的代码位于单独的独立文件中,您甚至可以使用 Alembic 执行迁移,而无需安装 FastAPI、Pydantic 或其他任何东西。
|
||||
|
||||
同样,您将能够在与**FastAPI**无关的代码的其他部分中使用相同的 SQLAlchemy 模型和实用程序。
|
||||
|
||||
例如,在具有[Celery](https://docs.celeryq.dev/)、[RQ](https://python-rq.org/)或[ARQ](https://arq-docs.helpmanual.io/)的后台任务工作者中。
|
||||
|
||||
## 审查所有文件
|
||||
|
||||
最后回顾整个案例,您应该有一个名为的目录`my_super_project`,其中包含一个名为`sql_app`。
|
||||
|
||||
`sql_app`中应该有以下文件:
|
||||
|
||||
* `sql_app/__init__.py`:这是一个空文件。
|
||||
|
||||
* `sql_app/database.py`:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/sql_databases/sql_app/database.py!}
|
||||
```
|
||||
|
||||
* `sql_app/models.py`:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/sql_databases/sql_app/models.py!}
|
||||
```
|
||||
|
||||
* `sql_app/schemas.py`:
|
||||
|
||||
=== "Python 3.6 及以上版本"
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 及以上版本"
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10 及以上版本"
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
|
||||
```
|
||||
|
||||
* `sql_app/crud.py`:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/sql_databases/sql_app/crud.py!}
|
||||
```
|
||||
|
||||
* `sql_app/main.py`:
|
||||
|
||||
=== "Python 3.6 及以上版本"
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 及以上版本"
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
|
||||
```
|
||||
|
||||
## 执行项目
|
||||
|
||||
您可以复制这些代码并按原样使用它。
|
||||
|
||||
!!! info
|
||||
|
||||
事实上,这里的代码只是大多数测试代码的一部分。
|
||||
|
||||
你可以用 Uvicorn 运行它:
|
||||
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn sql_app.main:app --reload
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
打开浏览器进入 <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs。</a>
|
||||
|
||||
您将能够与您的**FastAPI**应用程序交互,从真实数据库中读取数据:
|
||||
|
||||
<img src="/img/tutorial/sql-databases/image01.png">
|
||||
|
||||
## 直接与数据库交互
|
||||
|
||||
如果您想独立于 FastAPI 直接浏览 SQLite 数据库(文件)以调试其内容、添加表、列、记录、修改数据等,您可以使用[SQLite 的 DB Browser](https://sqlitebrowser.org/)
|
||||
|
||||
它看起来像这样:
|
||||
|
||||
<img src="/img/tutorial/sql-databases/image02.png">
|
||||
|
||||
您还可以使用[SQLite Viewer](https://inloop.github.io/sqlite-viewer/)或[ExtendsClass](https://extendsclass.com/sqlite-browser.html)等在线 SQLite 浏览器。
|
||||
|
||||
## 中间件替代数据库会话
|
||||
|
||||
如果你不能使用依赖项`yield`——例如,如果你没有使用**Python 3.7**并且不能安装上面提到的**Python 3.6**的“backports” ——你可以在类似的“中间件”中设置会话方法。
|
||||
|
||||
“中间件”基本功能是一个为每个请求执行的函数在请求之前进行执行相应的代码,以及在请求执行之后执行相应的代码。
|
||||
|
||||
### 创建中间件
|
||||
|
||||
我们将添加中间件(只是一个函数)将为每个请求创建一个新的 SQLAlchemy`SessionLocal`,将其添加到请求中,然后在请求完成后关闭它。
|
||||
|
||||
=== "Python 3.6 及以上版本"
|
||||
|
||||
```Python hl_lines="14-22"
|
||||
{!> ../../../docs_src/sql_databases/sql_app/alt_main.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9 及以上版本"
|
||||
|
||||
```Python hl_lines="12-20"
|
||||
{!> ../../../docs_src/sql_databases/sql_app_py39/alt_main.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
我们将`SessionLocal()`请求的创建和处理放在一个`try`块中。
|
||||
|
||||
然后我们在finally块中关闭它。
|
||||
|
||||
通过这种方式,我们确保数据库会话在请求后始终关闭,即使在处理请求时出现异常也会关闭。
|
||||
|
||||
### 关于`request.state`
|
||||
|
||||
`request.state`是每个`Request`对象的属性。它用于存储附加到请求本身的任意对象,例如本例中的数据库会话。您可以在[Starlette 的关于`Request`state](https://www.starlette.io/requests/#other-state)的文档中了解更多信息。
|
||||
|
||||
对于这种情况下,它帮助我们确保在所有请求中使用单个数据库会话,然后关闭(在中间件中)。
|
||||
|
||||
### 使用`yield`依赖项与使用中间件的区别
|
||||
|
||||
在此处添加**中间件**与`yield`的依赖项的作用效果类似,但也有一些区别:
|
||||
|
||||
* 中间件需要更多的代码并且更复杂一些。
|
||||
* 中间件必须是一个`async`函数。
|
||||
* 如果其中有代码必须“等待”网络,它可能会在那里“阻止”您的应用程序并稍微降低性能。
|
||||
* 尽管这里的`SQLAlchemy`工作方式可能不是很成问题。
|
||||
* 但是,如果您向等待大量I/O的中间件添加更多代码,则可能会出现问题。
|
||||
* *每个*请求都会运行一个中间件。
|
||||
* 将为每个请求创建一个连接。
|
||||
* 即使处理该请求的*路径操作*不需要数据库。
|
||||
|
||||
!!! tip
|
||||
`tyield`当依赖项 足以满足用例时,使用`tyield`依赖项方法会更好。
|
||||
|
||||
!!! info
|
||||
`yield`的依赖项是最近刚加入**FastAPI**中的。
|
||||
|
||||
所以本教程的先前版本只有带有中间件的示例,并且可能有多个应用程序使用中间件进行数据库会话管理。
|
||||
@@ -85,9 +85,11 @@ nav:
|
||||
- tutorial/request-forms-and-files.md
|
||||
- tutorial/handling-errors.md
|
||||
- tutorial/path-operation-configuration.md
|
||||
- tutorial/encoder.md
|
||||
- tutorial/body-updates.md
|
||||
- 依赖项:
|
||||
- tutorial/dependencies/index.md
|
||||
- tutorial/dependencies/classes-as-dependencies.md
|
||||
- tutorial/dependencies/sub-dependencies.md
|
||||
- tutorial/dependencies/dependencies-in-path-operation-decorators.md
|
||||
- tutorial/dependencies/global-dependencies.md
|
||||
@@ -98,6 +100,7 @@ nav:
|
||||
- tutorial/security/simple-oauth2.md
|
||||
- tutorial/security/oauth2-jwt.md
|
||||
- tutorial/cors.md
|
||||
- tutorial/sql-databases.md
|
||||
- tutorial/bigger-applications.md
|
||||
- tutorial/metadata.md
|
||||
- tutorial/debugging.md
|
||||
@@ -108,6 +111,7 @@ nav:
|
||||
- advanced/response-directly.md
|
||||
- advanced/custom-response.md
|
||||
- advanced/response-cookies.md
|
||||
- advanced/wsgi.md
|
||||
- contributing.md
|
||||
- help-fastapi.md
|
||||
- benchmarks.md
|
||||
|
||||
@@ -19,5 +19,4 @@ app = FastAPI()
|
||||
async def read_item(item_id: str):
|
||||
if item_id == "foo":
|
||||
return {"id": "foo", "value": "there goes my hero"}
|
||||
else:
|
||||
return JSONResponse(status_code=404, content={"message": "Item not found"})
|
||||
return JSONResponse(status_code=404, content={"message": "Item not found"})
|
||||
|
||||
@@ -6,4 +6,4 @@ app = FastAPI()
|
||||
|
||||
@app.get("/items/", response_class=ORJSONResponse)
|
||||
async def read_items():
|
||||
return [{"item_id": "Foo"}]
|
||||
return ORJSONResponse([{"item_id": "Foo"}])
|
||||
|
||||
19
docs_src/custom_response/tutorial009c.py
Normal file
19
docs_src/custom_response/tutorial009c.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from typing import Any
|
||||
|
||||
import orjson
|
||||
from fastapi import FastAPI, Response
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class CustomORJSONResponse(Response):
|
||||
media_type = "application/json"
|
||||
|
||||
def render(self, content: Any) -> bytes:
|
||||
assert orjson is not None, "orjson must be installed"
|
||||
return orjson.dumps(content, option=orjson.OPT_INDENT_2)
|
||||
|
||||
|
||||
@app.get("/", response_class=CustomORJSONResponse)
|
||||
async def main():
|
||||
return {"message": "Hello World"}
|
||||
@@ -14,7 +14,7 @@ app = FastAPI()
|
||||
|
||||
@app.get("/models/{model_name}")
|
||||
async def get_model(model_name: ModelName):
|
||||
if model_name == ModelName.alexnet:
|
||||
if model_name is ModelName.alexnet:
|
||||
return {"model_name": model_name, "message": "Deep Learning FTW!"}
|
||||
|
||||
if model_name.value == "lenet":
|
||||
|
||||
@@ -9,9 +9,17 @@ security = HTTPBasic()
|
||||
|
||||
|
||||
def get_current_username(credentials: HTTPBasicCredentials = Depends(security)):
|
||||
correct_username = secrets.compare_digest(credentials.username, "stanleyjobson")
|
||||
correct_password = secrets.compare_digest(credentials.password, "swordfish")
|
||||
if not (correct_username and correct_password):
|
||||
current_username_bytes = credentials.username.encode("utf8")
|
||||
correct_username_bytes = b"stanleyjobson"
|
||||
is_correct_username = secrets.compare_digest(
|
||||
current_username_bytes, correct_username_bytes
|
||||
)
|
||||
current_password_bytes = credentials.password.encode("utf8")
|
||||
correct_password_bytes = b"swordfish"
|
||||
is_correct_password = secrets.compare_digest(
|
||||
current_password_bytes, correct_password_bytes
|
||||
)
|
||||
if not (is_correct_username and is_correct_password):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Incorrect email or password",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
||||
|
||||
__version__ = "0.80.0"
|
||||
__version__ = "0.86.0"
|
||||
|
||||
from starlette import status as status
|
||||
|
||||
|
||||
@@ -33,9 +33,10 @@ from fastapi.types import DecoratedCallable
|
||||
from fastapi.utils import generate_unique_id
|
||||
from starlette.applications import Starlette
|
||||
from starlette.datastructures import State
|
||||
from starlette.exceptions import ExceptionMiddleware, HTTPException
|
||||
from starlette.exceptions import HTTPException
|
||||
from starlette.middleware import Middleware
|
||||
from starlette.middleware.errors import ServerErrorMiddleware
|
||||
from starlette.middleware.exceptions import ExceptionMiddleware
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import HTMLResponse, JSONResponse, Response
|
||||
from starlette.routing import BaseRoute
|
||||
@@ -635,10 +636,10 @@ class FastAPI(Starlette):
|
||||
response_description=response_description,
|
||||
responses=responses,
|
||||
deprecated=deprecated,
|
||||
operation_id=operation_id,
|
||||
response_model_include=response_model_include,
|
||||
response_model_exclude=response_model_exclude,
|
||||
response_model_by_alias=response_model_by_alias,
|
||||
operation_id=operation_id,
|
||||
response_model_exclude_unset=response_model_exclude_unset,
|
||||
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||
response_model_exclude_none=response_model_exclude_none,
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
import sys
|
||||
from contextlib import AsyncExitStack as AsyncExitStack # noqa
|
||||
from contextlib import asynccontextmanager as asynccontextmanager
|
||||
from typing import AsyncGenerator, ContextManager, TypeVar
|
||||
|
||||
import anyio
|
||||
from anyio import CapacityLimiter
|
||||
from starlette.concurrency import iterate_in_threadpool as iterate_in_threadpool # noqa
|
||||
from starlette.concurrency import run_in_threadpool as run_in_threadpool # noqa
|
||||
from starlette.concurrency import ( # noqa
|
||||
run_until_first_complete as run_until_first_complete,
|
||||
)
|
||||
|
||||
if sys.version_info >= (3, 7):
|
||||
from contextlib import AsyncExitStack as AsyncExitStack
|
||||
from contextlib import asynccontextmanager as asynccontextmanager
|
||||
else:
|
||||
from contextlib2 import AsyncExitStack as AsyncExitStack # noqa
|
||||
from contextlib2 import asynccontextmanager as asynccontextmanager # noqa
|
||||
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
||||
@@ -22,11 +17,24 @@ _T = TypeVar("_T")
|
||||
async def contextmanager_in_threadpool(
|
||||
cm: ContextManager[_T],
|
||||
) -> AsyncGenerator[_T, None]:
|
||||
# blocking __exit__ from running waiting on a free thread
|
||||
# can create race conditions/deadlocks if the context manager itself
|
||||
# has it's own internal pool (e.g. a database connection pool)
|
||||
# to avoid this we let __exit__ run without a capacity limit
|
||||
# since we're creating a new limiter for each call, any non-zero limit
|
||||
# works (1 is arbitrary)
|
||||
exit_limiter = CapacityLimiter(1)
|
||||
try:
|
||||
yield await run_in_threadpool(cm.__enter__)
|
||||
except Exception as e:
|
||||
ok: bool = await run_in_threadpool(cm.__exit__, type(e), e, None)
|
||||
ok = bool(
|
||||
await anyio.to_thread.run_sync(
|
||||
cm.__exit__, type(e), e, None, limiter=exit_limiter
|
||||
)
|
||||
)
|
||||
if not ok:
|
||||
raise e
|
||||
else:
|
||||
await run_in_threadpool(cm.__exit__, None, None, None)
|
||||
await anyio.to_thread.run_sync(
|
||||
cm.__exit__, None, None, None, limiter=exit_limiter
|
||||
)
|
||||
|
||||
@@ -7,6 +7,7 @@ from typing import (
|
||||
Callable,
|
||||
Coroutine,
|
||||
Dict,
|
||||
ForwardRef,
|
||||
List,
|
||||
Mapping,
|
||||
Optional,
|
||||
@@ -34,6 +35,7 @@ from pydantic import BaseModel, create_model
|
||||
from pydantic.error_wrappers import ErrorWrapper
|
||||
from pydantic.errors import MissingError
|
||||
from pydantic.fields import (
|
||||
SHAPE_FROZENSET,
|
||||
SHAPE_LIST,
|
||||
SHAPE_SEQUENCE,
|
||||
SHAPE_SET,
|
||||
@@ -46,7 +48,7 @@ from pydantic.fields import (
|
||||
Undefined,
|
||||
)
|
||||
from pydantic.schema import get_annotation_from_field_info
|
||||
from pydantic.typing import ForwardRef, evaluate_forwardref
|
||||
from pydantic.typing import evaluate_forwardref
|
||||
from pydantic.utils import lenient_issubclass
|
||||
from starlette.background import BackgroundTasks
|
||||
from starlette.concurrency import run_in_threadpool
|
||||
@@ -58,6 +60,7 @@ from starlette.websockets import WebSocket
|
||||
sequence_shapes = {
|
||||
SHAPE_LIST,
|
||||
SHAPE_SET,
|
||||
SHAPE_FROZENSET,
|
||||
SHAPE_TUPLE,
|
||||
SHAPE_SEQUENCE,
|
||||
SHAPE_TUPLE_ELLIPSIS,
|
||||
@@ -300,10 +303,7 @@ def get_dependant(
|
||||
assert is_scalar_field(
|
||||
field=param_field
|
||||
), "Path params must be of one of the supported types"
|
||||
if isinstance(param.default, params.Path):
|
||||
ignore_default = False
|
||||
else:
|
||||
ignore_default = True
|
||||
ignore_default = not isinstance(param.default, params.Path)
|
||||
param_field = get_param_field(
|
||||
param=param,
|
||||
param_name=param_name,
|
||||
@@ -426,22 +426,22 @@ def is_coroutine_callable(call: Callable[..., Any]) -> bool:
|
||||
return inspect.iscoroutinefunction(call)
|
||||
if inspect.isclass(call):
|
||||
return False
|
||||
call = getattr(call, "__call__", None)
|
||||
return inspect.iscoroutinefunction(call)
|
||||
dunder_call = getattr(call, "__call__", None)
|
||||
return inspect.iscoroutinefunction(dunder_call)
|
||||
|
||||
|
||||
def is_async_gen_callable(call: Callable[..., Any]) -> bool:
|
||||
if inspect.isasyncgenfunction(call):
|
||||
return True
|
||||
call = getattr(call, "__call__", None)
|
||||
return inspect.isasyncgenfunction(call)
|
||||
dunder_call = getattr(call, "__call__", None)
|
||||
return inspect.isasyncgenfunction(dunder_call)
|
||||
|
||||
|
||||
def is_gen_callable(call: Callable[..., Any]) -> bool:
|
||||
if inspect.isgeneratorfunction(call):
|
||||
return True
|
||||
call = getattr(call, "__call__", None)
|
||||
return inspect.isgeneratorfunction(call)
|
||||
dunder_call = getattr(call, "__call__", None)
|
||||
return inspect.isgeneratorfunction(dunder_call)
|
||||
|
||||
|
||||
async def solve_generator(
|
||||
|
||||
@@ -54,8 +54,8 @@ def jsonable_encoder(
|
||||
if custom_encoder:
|
||||
encoder.update(custom_encoder)
|
||||
obj_dict = obj.dict(
|
||||
include=include, # type: ignore # in Pydantic
|
||||
exclude=exclude, # type: ignore # in Pydantic
|
||||
include=include,
|
||||
exclude=exclude,
|
||||
by_alias=by_alias,
|
||||
exclude_unset=exclude_unset,
|
||||
exclude_none=exclude_none,
|
||||
@@ -71,7 +71,18 @@ def jsonable_encoder(
|
||||
sqlalchemy_safe=sqlalchemy_safe,
|
||||
)
|
||||
if dataclasses.is_dataclass(obj):
|
||||
return dataclasses.asdict(obj)
|
||||
obj_dict = dataclasses.asdict(obj)
|
||||
return jsonable_encoder(
|
||||
obj_dict,
|
||||
include=include,
|
||||
exclude=exclude,
|
||||
by_alias=by_alias,
|
||||
exclude_unset=exclude_unset,
|
||||
exclude_defaults=exclude_defaults,
|
||||
exclude_none=exclude_none,
|
||||
custom_encoder=custom_encoder,
|
||||
sqlalchemy_safe=sqlalchemy_safe,
|
||||
)
|
||||
if isinstance(obj, Enum):
|
||||
return obj.value
|
||||
if isinstance(obj, PurePath):
|
||||
@@ -137,10 +148,10 @@ def jsonable_encoder(
|
||||
if isinstance(obj, classes_tuple):
|
||||
return encoder(obj)
|
||||
|
||||
errors: List[Exception] = []
|
||||
try:
|
||||
data = dict(obj)
|
||||
except Exception as e:
|
||||
errors: List[Exception] = []
|
||||
errors.append(e)
|
||||
try:
|
||||
data = vars(obj)
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from fastapi.utils import is_body_allowed_for_status_code
|
||||
from starlette.exceptions import HTTPException
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import JSONResponse
|
||||
from starlette.responses import JSONResponse, Response
|
||||
from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY
|
||||
|
||||
|
||||
async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse:
|
||||
async def http_exception_handler(request: Request, exc: HTTPException) -> Response:
|
||||
headers = getattr(exc, "headers", None)
|
||||
if headers:
|
||||
return JSONResponse(
|
||||
{"detail": exc.detail}, status_code=exc.status_code, headers=headers
|
||||
)
|
||||
else:
|
||||
return JSONResponse({"detail": exc.detail}, status_code=exc.status_code)
|
||||
if not is_body_allowed_for_status_code(exc.status_code):
|
||||
return Response(status_code=exc.status_code, headers=headers)
|
||||
return JSONResponse(
|
||||
{"detail": exc.detail}, status_code=exc.status_code, headers=headers
|
||||
)
|
||||
|
||||
|
||||
async def request_validation_exception_handler(
|
||||
|
||||
@@ -106,6 +106,9 @@ def get_redoc_html(
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
ReDoc requires Javascript to function. Please enable it to browse the documentation.
|
||||
</noscript>
|
||||
<redoc spec-url="{openapi_url}"></redoc>
|
||||
<script src="{redoc_js_url}"> </script>
|
||||
</body>
|
||||
|
||||
@@ -222,11 +222,18 @@ def get_openapi_path(
|
||||
)
|
||||
parameters.extend(operation_parameters)
|
||||
if parameters:
|
||||
operation["parameters"] = list(
|
||||
{
|
||||
(param["in"], param["name"]): param for param in parameters
|
||||
}.values()
|
||||
)
|
||||
all_parameters = {
|
||||
(param["in"], param["name"]): param for param in parameters
|
||||
}
|
||||
required_parameters = {
|
||||
(param["in"], param["name"]): param
|
||||
for param in parameters
|
||||
if param.get("required")
|
||||
}
|
||||
# Make sure required definitions of the same parameter take precedence
|
||||
# over non-required definitions
|
||||
all_parameters.update(required_parameters)
|
||||
operation["parameters"] = list(all_parameters.values())
|
||||
if method in METHODS_WITH_BODY:
|
||||
request_body_oai = get_openapi_operation_request_body(
|
||||
body_field=route.body_field, model_name_map=model_name_map
|
||||
|
||||
@@ -31,4 +31,6 @@ class ORJSONResponse(JSONResponse):
|
||||
|
||||
def render(self, content: Any) -> bytes:
|
||||
assert orjson is not None, "orjson must be installed to use ORJSONResponse"
|
||||
return orjson.dumps(content)
|
||||
return orjson.dumps(
|
||||
content, option=orjson.OPT_NON_STR_KEYS | orjson.OPT_SERIALIZE_NUMPY
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ import dataclasses
|
||||
import email.message
|
||||
import inspect
|
||||
import json
|
||||
from contextlib import AsyncExitStack
|
||||
from enum import Enum, IntEnum
|
||||
from typing import (
|
||||
Any,
|
||||
@@ -127,7 +128,7 @@ async def serialize_response(
|
||||
if is_coroutine:
|
||||
value, errors_ = field.validate(response_content, {}, loc=("response",))
|
||||
else:
|
||||
value, errors_ = await run_in_threadpool( # type: ignore[misc]
|
||||
value, errors_ = await run_in_threadpool(
|
||||
field.validate, response_content, {}, loc=("response",)
|
||||
)
|
||||
if isinstance(errors_, ErrorWrapper):
|
||||
@@ -190,6 +191,9 @@ def get_request_handler(
|
||||
if body_field:
|
||||
if is_body_form:
|
||||
body = await request.form()
|
||||
stack = request.scope.get("fastapi_astack")
|
||||
assert isinstance(stack, AsyncExitStack)
|
||||
stack.push_async_callback(body.close)
|
||||
else:
|
||||
body_bytes = await request.body()
|
||||
if body_bytes:
|
||||
@@ -209,7 +213,11 @@ def get_request_handler(
|
||||
else:
|
||||
body = body_bytes
|
||||
except json.JSONDecodeError as e:
|
||||
raise RequestValidationError([ErrorWrapper(e, ("body", e.pos))], body=e.doc)
|
||||
raise RequestValidationError(
|
||||
[ErrorWrapper(e, ("body", e.pos))], body=e.doc
|
||||
) from e
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=400, detail="There was an error parsing the body"
|
||||
@@ -254,7 +262,7 @@ def get_request_handler(
|
||||
is_coroutine=is_coroutine,
|
||||
)
|
||||
response = actual_response_class(content, **response_args)
|
||||
if not is_body_allowed_for_status_code(status_code):
|
||||
if not is_body_allowed_for_status_code(response.status_code):
|
||||
response.body = b""
|
||||
response.headers.raw.extend(sub_response.headers.raw)
|
||||
return response
|
||||
@@ -293,14 +301,14 @@ class APIWebSocketRoute(routing.WebSocketRoute):
|
||||
self.path = path
|
||||
self.endpoint = endpoint
|
||||
self.name = get_name(endpoint) if name is None else name
|
||||
self.dependant = get_dependant(path=path, call=self.endpoint)
|
||||
self.path_regex, self.path_format, self.param_convertors = compile_path(path)
|
||||
self.dependant = get_dependant(path=self.path_format, call=self.endpoint)
|
||||
self.app = websocket_session(
|
||||
get_websocket_app(
|
||||
dependant=self.dependant,
|
||||
dependency_overrides_provider=dependency_overrides_provider,
|
||||
)
|
||||
)
|
||||
self.path_regex, self.path_format, self.param_convertors = compile_path(path)
|
||||
|
||||
def matches(self, scope: Scope) -> Tuple[Match, Scope]:
|
||||
match, child_scope = super().matches(scope)
|
||||
|
||||
@@ -27,7 +27,7 @@ class APIKeyQuery(APIKeyBase):
|
||||
self.auto_error = auto_error
|
||||
|
||||
async def __call__(self, request: Request) -> Optional[str]:
|
||||
api_key: str = request.query_params.get(self.model.name)
|
||||
api_key = request.query_params.get(self.model.name)
|
||||
if not api_key:
|
||||
if self.auto_error:
|
||||
raise HTTPException(
|
||||
|
||||
@@ -119,7 +119,7 @@ class OAuth2(SecurityBase):
|
||||
flows: Union[OAuthFlowsModel, Dict[str, Dict[str, Any]]] = OAuthFlowsModel(),
|
||||
scheme_name: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
auto_error: Optional[bool] = True
|
||||
auto_error: bool = True
|
||||
):
|
||||
self.model = OAuth2Model(flows=flows, description=description)
|
||||
self.scheme_name = scheme_name or self.__class__.__name__
|
||||
|
||||
@@ -21,6 +21,16 @@ if TYPE_CHECKING: # pragma: nocover
|
||||
def is_body_allowed_for_status_code(status_code: Union[int, str, None]) -> bool:
|
||||
if status_code is None:
|
||||
return True
|
||||
# Ref: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#patterned-fields-1
|
||||
if status_code in {
|
||||
"default",
|
||||
"1XX",
|
||||
"2XX",
|
||||
"3XX",
|
||||
"4XX",
|
||||
"5XX",
|
||||
}:
|
||||
return True
|
||||
current_status_code = int(status_code)
|
||||
return not (current_status_code < 200 or current_status_code in {204, 304})
|
||||
|
||||
@@ -37,6 +47,8 @@ def get_model_definitions(
|
||||
)
|
||||
definitions.update(m_definitions)
|
||||
model_name = model_name_map[model]
|
||||
if "description" in m_schema:
|
||||
m_schema["description"] = m_schema["description"].split("\f")[0]
|
||||
definitions[model_name] = m_schema
|
||||
return definitions
|
||||
|
||||
@@ -87,7 +99,7 @@ def create_cloned_field(
|
||||
) -> ModelField:
|
||||
# _cloned_types has already cloned types, to support recursive models
|
||||
if cloned_types is None:
|
||||
cloned_types = dict()
|
||||
cloned_types = {}
|
||||
original_type = field.type_
|
||||
if is_dataclass(original_type) and hasattr(original_type, "__pydantic_model__"):
|
||||
original_type = original_type.__pydantic_model__
|
||||
@@ -140,14 +152,14 @@ def generate_operation_id_for_path(
|
||||
stacklevel=2,
|
||||
)
|
||||
operation_id = name + path
|
||||
operation_id = re.sub("[^0-9a-zA-Z_]", "_", operation_id)
|
||||
operation_id = re.sub(r"\W", "_", operation_id)
|
||||
operation_id = operation_id + "_" + method.lower()
|
||||
return operation_id
|
||||
|
||||
|
||||
def generate_unique_id(route: "APIRoute") -> str:
|
||||
operation_id = route.name + route.path_format
|
||||
operation_id = re.sub("[^0-9a-zA-Z_]", "_", operation_id)
|
||||
operation_id = re.sub(r"\W", "_", operation_id)
|
||||
assert route.methods
|
||||
operation_id = operation_id + "_" + list(route.methods)[0].lower()
|
||||
return operation_id
|
||||
@@ -161,6 +173,12 @@ def deep_dict_update(main_dict: Dict[Any, Any], update_dict: Dict[Any, Any]) ->
|
||||
and isinstance(value, dict)
|
||||
):
|
||||
deep_dict_update(main_dict[key], value)
|
||||
elif (
|
||||
key in main_dict
|
||||
and isinstance(main_dict[key], list)
|
||||
and isinstance(update_dict[key], list)
|
||||
):
|
||||
main_dict[key] = main_dict[key] + update_dict[key]
|
||||
else:
|
||||
main_dict[key] = value
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
from starlette.websockets import WebSocket as WebSocket # noqa
|
||||
from starlette.websockets import WebSocketDisconnect as WebSocketDisconnect # noqa
|
||||
from starlette.websockets import WebSocketState as WebSocketState # noqa
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user