Merge branch 'master' into feature/translation-fr-deployment-deta
|
|
@ -1,7 +1,7 @@
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional
|
from typing import Union
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
from github import Github
|
from github import Github
|
||||||
|
|
@ -14,7 +14,7 @@ github_api = "https://api.github.com"
|
||||||
class Settings(BaseSettings):
|
class Settings(BaseSettings):
|
||||||
github_repository: str
|
github_repository: str
|
||||||
github_event_path: Path
|
github_event_path: Path
|
||||||
github_event_name: Optional[str] = None
|
github_event_name: Union[str, None] = None
|
||||||
input_token: SecretStr
|
input_token: SecretStr
|
||||||
input_deploy_url: str
|
input_deploy_url: str
|
||||||
|
|
||||||
|
|
@ -42,15 +42,13 @@ if __name__ == "__main__":
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
logging.error(f"Error parsing event file: {e.errors()}")
|
logging.error(f"Error parsing event file: {e.errors()}")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
use_pr: Optional[PullRequest] = None
|
use_pr: Union[PullRequest, None] = None
|
||||||
for pr in repo.get_pulls():
|
for pr in repo.get_pulls():
|
||||||
if pr.head.sha == event.workflow_run.head_commit.id:
|
if pr.head.sha == event.workflow_run.head_commit.id:
|
||||||
use_pr = pr
|
use_pr = pr
|
||||||
break
|
break
|
||||||
if not use_pr:
|
if not use_pr:
|
||||||
logging.error(
|
logging.error(f"No PR found for hash: {event.workflow_run.head_commit.id}")
|
||||||
f"No PR found for hash: {event.workflow_run.head_commit.id}"
|
|
||||||
)
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
github_headers = {
|
github_headers = {
|
||||||
"Authorization": f"token {settings.input_token.get_secret_value()}"
|
"Authorization": f"token {settings.input_token.get_secret_value()}"
|
||||||
|
|
|
||||||
10
.github/actions/notify-translations/app/main.py
vendored
|
|
@ -1,8 +1,8 @@
|
||||||
import logging
|
import logging
|
||||||
|
import random
|
||||||
import time
|
import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import random
|
from typing import Dict, Union
|
||||||
from typing import Dict, Optional
|
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
from github import Github
|
from github import Github
|
||||||
|
|
@ -18,8 +18,8 @@ class Settings(BaseSettings):
|
||||||
github_repository: str
|
github_repository: str
|
||||||
input_token: SecretStr
|
input_token: SecretStr
|
||||||
github_event_path: Path
|
github_event_path: Path
|
||||||
github_event_name: Optional[str] = None
|
github_event_name: Union[str, None] = None
|
||||||
input_debug: Optional[bool] = False
|
input_debug: Union[bool, None] = False
|
||||||
|
|
||||||
|
|
||||||
class PartialGitHubEventIssue(BaseModel):
|
class PartialGitHubEventIssue(BaseModel):
|
||||||
|
|
@ -54,7 +54,7 @@ if __name__ == "__main__":
|
||||||
)
|
)
|
||||||
if pr.state == "open":
|
if pr.state == "open":
|
||||||
logging.debug(f"PR is open: {pr.number}")
|
logging.debug(f"PR is open: {pr.number}")
|
||||||
label_strs = set([label.name for label in pr.get_labels()])
|
label_strs = {label.name for label in pr.get_labels()}
|
||||||
if lang_all_label in label_strs and awaiting_label in label_strs:
|
if lang_all_label in label_strs and awaiting_label in label_strs:
|
||||||
logging.info(
|
logging.info(
|
||||||
f"This PR seems to be a language translation and awaiting reviews: {pr.number}"
|
f"This PR seems to be a language translation and awaiting reviews: {pr.number}"
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,13 @@ uk: 1748
|
||||||
tr: 1892
|
tr: 1892
|
||||||
fr: 1972
|
fr: 1972
|
||||||
ko: 2017
|
ko: 2017
|
||||||
sq: 2041
|
fa: 2041
|
||||||
pl: 3169
|
pl: 3169
|
||||||
de: 3716
|
de: 3716
|
||||||
id: 3717
|
id: 3717
|
||||||
az: 3994
|
az: 3994
|
||||||
nl: 4701
|
nl: 4701
|
||||||
uz: 4883
|
uz: 4883
|
||||||
|
sv: 5146
|
||||||
|
he: 5157
|
||||||
|
ta: 5434
|
||||||
|
|
|
||||||
22
.github/actions/people/app/main.py
vendored
|
|
@ -4,7 +4,7 @@ import sys
|
||||||
from collections import Counter, defaultdict
|
from collections import Counter, defaultdict
|
||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Container, DefaultDict, Dict, List, Optional, Set
|
from typing import Container, DefaultDict, Dict, List, Set, Union
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
import yaml
|
import yaml
|
||||||
|
|
@ -133,7 +133,7 @@ class Author(BaseModel):
|
||||||
|
|
||||||
class CommentsNode(BaseModel):
|
class CommentsNode(BaseModel):
|
||||||
createdAt: datetime
|
createdAt: datetime
|
||||||
author: Optional[Author] = None
|
author: Union[Author, None] = None
|
||||||
|
|
||||||
|
|
||||||
class Comments(BaseModel):
|
class Comments(BaseModel):
|
||||||
|
|
@ -142,7 +142,7 @@ class Comments(BaseModel):
|
||||||
|
|
||||||
class IssuesNode(BaseModel):
|
class IssuesNode(BaseModel):
|
||||||
number: int
|
number: int
|
||||||
author: Optional[Author] = None
|
author: Union[Author, None] = None
|
||||||
title: str
|
title: str
|
||||||
createdAt: datetime
|
createdAt: datetime
|
||||||
state: str
|
state: str
|
||||||
|
|
@ -179,7 +179,7 @@ class Labels(BaseModel):
|
||||||
|
|
||||||
|
|
||||||
class ReviewNode(BaseModel):
|
class ReviewNode(BaseModel):
|
||||||
author: Optional[Author] = None
|
author: Union[Author, None] = None
|
||||||
state: str
|
state: str
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -190,7 +190,7 @@ class Reviews(BaseModel):
|
||||||
class PullRequestNode(BaseModel):
|
class PullRequestNode(BaseModel):
|
||||||
number: int
|
number: int
|
||||||
labels: Labels
|
labels: Labels
|
||||||
author: Optional[Author] = None
|
author: Union[Author, None] = None
|
||||||
title: str
|
title: str
|
||||||
createdAt: datetime
|
createdAt: datetime
|
||||||
state: str
|
state: str
|
||||||
|
|
@ -260,19 +260,21 @@ class Settings(BaseSettings):
|
||||||
input_token: SecretStr
|
input_token: SecretStr
|
||||||
input_standard_token: SecretStr
|
input_standard_token: SecretStr
|
||||||
github_repository: str
|
github_repository: str
|
||||||
|
httpx_timeout: int = 30
|
||||||
|
|
||||||
|
|
||||||
def get_graphql_response(
|
def get_graphql_response(
|
||||||
*, settings: Settings, query: str, after: Optional[str] = None
|
*, settings: Settings, query: str, after: Union[str, None] = None
|
||||||
):
|
):
|
||||||
headers = {"Authorization": f"token {settings.input_token.get_secret_value()}"}
|
headers = {"Authorization": f"token {settings.input_token.get_secret_value()}"}
|
||||||
variables = {"after": after}
|
variables = {"after": after}
|
||||||
response = httpx.post(
|
response = httpx.post(
|
||||||
github_graphql_url,
|
github_graphql_url,
|
||||||
headers=headers,
|
headers=headers,
|
||||||
|
timeout=settings.httpx_timeout,
|
||||||
json={"query": query, "variables": variables, "operationName": "Q"},
|
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(f"Response was not 200, after: {after}")
|
||||||
logging.error(response.text)
|
logging.error(response.text)
|
||||||
raise RuntimeError(response.text)
|
raise RuntimeError(response.text)
|
||||||
|
|
@ -280,19 +282,19 @@ def get_graphql_response(
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def get_graphql_issue_edges(*, settings: Settings, after: Optional[str] = None):
|
def get_graphql_issue_edges(*, settings: Settings, after: Union[str, None] = None):
|
||||||
data = get_graphql_response(settings=settings, query=issues_query, after=after)
|
data = get_graphql_response(settings=settings, query=issues_query, after=after)
|
||||||
graphql_response = IssuesResponse.parse_obj(data)
|
graphql_response = IssuesResponse.parse_obj(data)
|
||||||
return graphql_response.data.repository.issues.edges
|
return graphql_response.data.repository.issues.edges
|
||||||
|
|
||||||
|
|
||||||
def get_graphql_pr_edges(*, settings: Settings, after: Optional[str] = None):
|
def get_graphql_pr_edges(*, settings: Settings, after: Union[str, None] = None):
|
||||||
data = get_graphql_response(settings=settings, query=prs_query, after=after)
|
data = get_graphql_response(settings=settings, query=prs_query, after=after)
|
||||||
graphql_response = PRsResponse.parse_obj(data)
|
graphql_response = PRsResponse.parse_obj(data)
|
||||||
return graphql_response.data.repository.pullRequests.edges
|
return graphql_response.data.repository.pullRequests.edges
|
||||||
|
|
||||||
|
|
||||||
def get_graphql_sponsor_edges(*, settings: Settings, after: Optional[str] = None):
|
def get_graphql_sponsor_edges(*, settings: Settings, after: Union[str, None] = None):
|
||||||
data = get_graphql_response(settings=settings, query=sponsors_query, after=after)
|
data = get_graphql_response(settings=settings, query=sponsors_query, after=after)
|
||||||
graphql_response = SponsorsResponse.parse_obj(data)
|
graphql_response = SponsorsResponse.parse_obj(data)
|
||||||
return graphql_response.data.user.sponsorshipsAsMaintainer.edges
|
return graphql_response.data.user.sponsorshipsAsMaintainer.edges
|
||||||
|
|
|
||||||
6
.github/actions/watch-previews/app/main.py
vendored
|
|
@ -1,7 +1,7 @@
|
||||||
import logging
|
import logging
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Optional
|
from typing import List, Union
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
from github import Github
|
from github import Github
|
||||||
|
|
@ -16,7 +16,7 @@ class Settings(BaseSettings):
|
||||||
input_token: SecretStr
|
input_token: SecretStr
|
||||||
github_repository: str
|
github_repository: str
|
||||||
github_event_path: Path
|
github_event_path: Path
|
||||||
github_event_name: Optional[str] = None
|
github_event_name: Union[str, None] = None
|
||||||
|
|
||||||
|
|
||||||
class Artifact(BaseModel):
|
class Artifact(BaseModel):
|
||||||
|
|
@ -74,7 +74,7 @@ if __name__ == "__main__":
|
||||||
logging.info(f"Docs preview was notified: {notified}")
|
logging.info(f"Docs preview was notified: {notified}")
|
||||||
if not notified:
|
if not notified:
|
||||||
artifact_name = f"docs-zip-{commit}"
|
artifact_name = f"docs-zip-{commit}"
|
||||||
use_artifact: Optional[Artifact] = None
|
use_artifact: Union[Artifact, None] = None
|
||||||
for artifact in artifacts_response.artifacts:
|
for artifact in artifacts_response.artifacts:
|
||||||
if artifact.name == artifact_name:
|
if artifact.name == artifact_name:
|
||||||
use_artifact = artifact
|
use_artifact = artifact
|
||||||
|
|
|
||||||
16
.github/dependabot.yml
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
# GitHub Actions
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
commit-message:
|
||||||
|
prefix: ⬆
|
||||||
|
# Python
|
||||||
|
- package-ecosystem: "pip"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
commit-message:
|
||||||
|
prefix: ⬆
|
||||||
21
.github/workflows/build-docs.yml
vendored
|
|
@ -13,35 +13,32 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: "3.7"
|
python-version: "3.7"
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v3
|
||||||
id: cache
|
id: cache
|
||||||
with:
|
with:
|
||||||
path: ${{ env.pythonLocation }}
|
path: ${{ env.pythonLocation }}
|
||||||
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-docs-v2
|
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
|
- name: Install docs extras
|
||||||
if: steps.cache.outputs.cache-hit != 'true'
|
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
|
- name: Install Material for MkDocs Insiders
|
||||||
if: github.event.pull_request.head.repo.fork == false && steps.cache.outputs.cache-hit != 'true'
|
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
|
run: pip install git+https://${{ secrets.ACTIONS_TOKEN }}@github.com/squidfunk/mkdocs-material-insiders.git
|
||||||
- name: Build Docs
|
- name: Build Docs
|
||||||
run: python3.7 ./scripts/docs.py build-all
|
run: python ./scripts/docs.py build-all
|
||||||
- name: Zip docs
|
- name: Zip docs
|
||||||
run: bash ./scripts/zip-docs.sh
|
run: bash ./scripts/zip-docs.sh
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: docs-zip
|
name: docs-zip
|
||||||
path: ./docs.zip
|
path: ./docs.zip
|
||||||
- name: Deploy to Netlify
|
- name: Deploy to Netlify
|
||||||
uses: nwtgck/actions-netlify@v1.1.5
|
uses: nwtgck/actions-netlify@v1.2.4
|
||||||
with:
|
with:
|
||||||
publish-dir: './site'
|
publish-dir: './site'
|
||||||
production-branch: master
|
production-branch: master
|
||||||
|
|
|
||||||
2
.github/workflows/latest-changes.yml
vendored
|
|
@ -20,7 +20,7 @@ jobs:
|
||||||
latest-changes:
|
latest-changes:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
# To allow latest-changes to commit to master
|
# To allow latest-changes to commit to master
|
||||||
token: ${{ secrets.ACTIONS_TOKEN }}
|
token: ${{ secrets.ACTIONS_TOKEN }}
|
||||||
|
|
|
||||||
2
.github/workflows/notify-translations.yml
vendored
|
|
@ -9,7 +9,7 @@ jobs:
|
||||||
notify-translations:
|
notify-translations:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
# Allow debugging with tmate
|
# Allow debugging with tmate
|
||||||
- name: Setup tmate session
|
- name: Setup tmate session
|
||||||
uses: mxschmitt/action-tmate@v3
|
uses: mxschmitt/action-tmate@v3
|
||||||
|
|
|
||||||
2
.github/workflows/people.yml
vendored
|
|
@ -14,7 +14,7 @@ jobs:
|
||||||
fastapi-people:
|
fastapi-people:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
# Allow debugging with tmate
|
# Allow debugging with tmate
|
||||||
- name: Setup tmate session
|
- name: Setup tmate session
|
||||||
uses: mxschmitt/action-tmate@v3
|
uses: mxschmitt/action-tmate@v3
|
||||||
|
|
|
||||||
6
.github/workflows/preview-docs.yml
vendored
|
|
@ -10,9 +10,9 @@ jobs:
|
||||||
preview-docs:
|
preview-docs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Download Artifact Docs
|
- name: Download Artifact Docs
|
||||||
uses: dawidd6/action-download-artifact@v2.9.0
|
uses: dawidd6/action-download-artifact@v2.24.0
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
workflow: build-docs.yml
|
workflow: build-docs.yml
|
||||||
|
|
@ -25,7 +25,7 @@ jobs:
|
||||||
rm -f docs.zip
|
rm -f docs.zip
|
||||||
- name: Deploy to Netlify
|
- name: Deploy to Netlify
|
||||||
id: netlify
|
id: netlify
|
||||||
uses: nwtgck/actions-netlify@v1.1.5
|
uses: nwtgck/actions-netlify@v1.2.4
|
||||||
with:
|
with:
|
||||||
publish-dir: './site'
|
publish-dir: './site'
|
||||||
production-deploy: false
|
production-deploy: false
|
||||||
|
|
|
||||||
24
.github/workflows/publish.yml
vendored
|
|
@ -13,27 +13,25 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: "3.6"
|
python-version: "3.7"
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v3
|
||||||
id: cache
|
id: cache
|
||||||
with:
|
with:
|
||||||
path: ${{ env.pythonLocation }}
|
path: ${{ env.pythonLocation }}
|
||||||
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-publish
|
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-publish
|
||||||
- name: Install Flit
|
- name: Install build dependencies
|
||||||
if: steps.cache.outputs.cache-hit != 'true'
|
if: steps.cache.outputs.cache-hit != 'true'
|
||||||
run: pip install flit
|
run: pip install build
|
||||||
- name: Install Dependencies
|
- name: Build distribution
|
||||||
if: steps.cache.outputs.cache-hit != 'true'
|
run: python -m build
|
||||||
run: flit install --symlink
|
|
||||||
- name: Publish
|
- name: Publish
|
||||||
env:
|
uses: pypa/gh-action-pypi-publish@v1.5.1
|
||||||
FLIT_USERNAME: ${{ secrets.FLIT_USERNAME }}
|
with:
|
||||||
FLIT_PASSWORD: ${{ secrets.FLIT_PASSWORD }}
|
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||||
run: bash scripts/publish.sh
|
|
||||||
- name: Dump GitHub context
|
- name: Dump GitHub context
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
|
|
|
||||||
16
.github/workflows/test.yml
vendored
|
|
@ -12,30 +12,26 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
|
python-version: ["3.7", "3.8", "3.9", "3.10"]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v3
|
||||||
id: cache
|
id: cache
|
||||||
with:
|
with:
|
||||||
path: ${{ env.pythonLocation }}
|
path: ${{ env.pythonLocation }}
|
||||||
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test-v02
|
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
|
- name: Install Dependencies
|
||||||
if: steps.cache.outputs.cache-hit != 'true'
|
if: steps.cache.outputs.cache-hit != 'true'
|
||||||
run: flit install --symlink
|
run: pip install -e .[all,dev,doc,test]
|
||||||
- name: Lint
|
- name: Lint
|
||||||
if: ${{ matrix.python-version != '3.6' }}
|
|
||||||
run: bash scripts/lint.sh
|
run: bash scripts/lint.sh
|
||||||
- name: Test
|
- name: Test
|
||||||
run: bash scripts/test.sh
|
run: bash scripts/test.sh
|
||||||
- name: Upload coverage
|
- name: Upload coverage
|
||||||
uses: codecov/codecov-action@v2
|
uses: codecov/codecov-action@v3
|
||||||
|
|
|
||||||
51
.pre-commit-config.yaml
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
# See https://pre-commit.com for more information
|
||||||
|
# See https://pre-commit.com/hooks.html for more hooks
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v4.3.0
|
||||||
|
hooks:
|
||||||
|
- id: check-added-large-files
|
||||||
|
- id: check-toml
|
||||||
|
- id: check-yaml
|
||||||
|
args:
|
||||||
|
- --unsafe
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: trailing-whitespace
|
||||||
|
- repo: https://github.com/asottile/pyupgrade
|
||||||
|
rev: v3.1.0
|
||||||
|
hooks:
|
||||||
|
- id: pyupgrade
|
||||||
|
args:
|
||||||
|
- --py3-plus
|
||||||
|
- --keep-runtime-typing
|
||||||
|
- repo: https://github.com/PyCQA/autoflake
|
||||||
|
rev: v1.7.7
|
||||||
|
hooks:
|
||||||
|
- id: autoflake
|
||||||
|
args:
|
||||||
|
- --recursive
|
||||||
|
- --in-place
|
||||||
|
- --remove-all-unused-imports
|
||||||
|
- --remove-unused-variables
|
||||||
|
- --expand-star-imports
|
||||||
|
- --exclude
|
||||||
|
- __init__.py
|
||||||
|
- --remove-duplicate-keys
|
||||||
|
- repo: https://github.com/pycqa/isort
|
||||||
|
rev: 5.10.1
|
||||||
|
hooks:
|
||||||
|
- id: isort
|
||||||
|
name: isort (python)
|
||||||
|
- id: isort
|
||||||
|
name: isort (cython)
|
||||||
|
types: [cython]
|
||||||
|
- id: isort
|
||||||
|
name: isort (pyi)
|
||||||
|
types: [pyi]
|
||||||
|
- repo: https://github.com/psf/black
|
||||||
|
rev: 22.10.0
|
||||||
|
hooks:
|
||||||
|
- id: black
|
||||||
|
ci:
|
||||||
|
autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks
|
||||||
|
autoupdate_commit_msg: ⬆ [pre-commit.ci] pre-commit autoupdate
|
||||||
29
README.md
|
|
@ -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:
|
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**: 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%. *
|
* **Fast to code**: Increase the speed to develop features by about 200% to 300%. *
|
||||||
* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. *
|
* **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.
|
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
|
||||||
|
|
@ -47,10 +46,10 @@ The key features are:
|
||||||
|
|
||||||
<!-- sponsors -->
|
<!-- sponsors -->
|
||||||
|
|
||||||
<a href="https://bit.ly/2QSouzH" target="_blank" title="Jina: build neural search-as-a-service for any kind of data in just minutes."><img src="https://fastapi.tiangolo.com/img/sponsors/jina.svg"></a>
|
<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://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://classiq.link/n4s" target="_blank" title="Join the team building a new SaaS platform that will change the computing world"><img src="https://fastapi.tiangolo.com/img/sponsors/classiq.png"></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.dropbase.io/careers" target="_blank" title="Dropbase - seamlessly collect, clean, and centralize data."><img src="https://fastapi.tiangolo.com/img/sponsors/dropbase.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.deta.sh/?ref=fastapi" target="_blank" title="The launchpad for all your (team's) ideas"><img src="https://fastapi.tiangolo.com/img/sponsors/deta.svg"></a>
|
||||||
<a href="https://www.investsuite.com/jobs" target="_blank" title="Wealthtech jobs with FastAPI"><img src="https://fastapi.tiangolo.com/img/sponsors/investsuite.svg"></a>
|
<a href="https://www.investsuite.com/jobs" target="_blank" title="Wealthtech jobs with FastAPI"><img src="https://fastapi.tiangolo.com/img/sponsors/investsuite.svg"></a>
|
||||||
<a href="https://training.talkpython.fm/fastapi-courses" target="_blank" title="FastAPI video courses on demand from people you trust"><img src="https://fastapi.tiangolo.com/img/sponsors/talkpython.png"></a>
|
<a href="https://training.talkpython.fm/fastapi-courses" target="_blank" title="FastAPI video courses on demand from people you trust"><img src="https://fastapi.tiangolo.com/img/sponsors/talkpython.png"></a>
|
||||||
|
|
@ -113,7 +112,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
Python 3.6+
|
Python 3.7+
|
||||||
|
|
||||||
FastAPI stands on the shoulders of giants:
|
FastAPI stands on the shoulders of giants:
|
||||||
|
|
||||||
|
|
@ -132,7 +131,7 @@ $ pip install fastapi
|
||||||
|
|
||||||
</div>
|
</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">
|
<div class="termy">
|
||||||
|
|
||||||
|
|
@ -151,7 +150,7 @@ $ pip install "uvicorn[standard]"
|
||||||
* Create a file `main.py` with:
|
* Create a file `main.py` with:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
from typing import Optional
|
from typing import Union
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
|
@ -164,7 +163,7 @@ def read_root():
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
def read_item(item_id: int, q: Optional[str] = None):
|
def read_item(item_id: int, q: Union[str, None] = None):
|
||||||
return {"item_id": item_id, "q": q}
|
return {"item_id": item_id, "q": q}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -174,7 +173,7 @@ def read_item(item_id: int, q: Optional[str] = None):
|
||||||
If your code uses `async` / `await`, use `async def`:
|
If your code uses `async` / `await`, use `async def`:
|
||||||
|
|
||||||
```Python hl_lines="9 14"
|
```Python hl_lines="9 14"
|
||||||
from typing import Optional
|
from typing import Union
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
|
@ -187,7 +186,7 @@ async def read_root():
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
async def read_item(item_id: int, q: Optional[str] = None):
|
async def read_item(item_id: int, q: Union[str, None] = None):
|
||||||
return {"item_id": item_id, "q": q}
|
return {"item_id": item_id, "q": q}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -266,7 +265,7 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
|
||||||
Declare the body using standard Python types, thanks to Pydantic.
|
Declare the body using standard Python types, thanks to Pydantic.
|
||||||
|
|
||||||
```Python hl_lines="4 9-12 25-27"
|
```Python hl_lines="4 9-12 25-27"
|
||||||
from typing import Optional
|
from typing import Union
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
@ -277,7 +276,7 @@ app = FastAPI()
|
||||||
class Item(BaseModel):
|
class Item(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
price: float
|
price: float
|
||||||
is_offer: Optional[bool] = None
|
is_offer: Union[bool, None] = None
|
||||||
|
|
||||||
|
|
||||||
@app.get("/")
|
@app.get("/")
|
||||||
|
|
@ -286,7 +285,7 @@ def read_root():
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
def read_item(item_id: int, q: Optional[str] = None):
|
def read_item(item_id: int, q: Union[str, None] = None):
|
||||||
return {"item_id": item_id, "q": q}
|
return {"item_id": item_id, "q": q}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -329,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.
|
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`:
|
For example, for an `int`:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ Learn more about it below. 👇
|
||||||
|
|
||||||
## Versions
|
## 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**.
|
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
|
|
@ -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.
|
||||||
|
|
@ -5,13 +5,15 @@ theme:
|
||||||
name: material
|
name: material
|
||||||
custom_dir: overrides
|
custom_dir: overrides
|
||||||
palette:
|
palette:
|
||||||
- scheme: default
|
- media: '(prefers-color-scheme: light)'
|
||||||
|
scheme: default
|
||||||
primary: teal
|
primary: teal
|
||||||
accent: amber
|
accent: amber
|
||||||
toggle:
|
toggle:
|
||||||
icon: material/lightbulb
|
icon: material/lightbulb
|
||||||
name: Switch to light mode
|
name: Switch to light mode
|
||||||
- scheme: slate
|
- media: '(prefers-color-scheme: dark)'
|
||||||
|
scheme: slate
|
||||||
primary: teal
|
primary: teal
|
||||||
accent: amber
|
accent: amber
|
||||||
toggle:
|
toggle:
|
||||||
|
|
@ -42,6 +44,7 @@ nav:
|
||||||
- es: /es/
|
- es: /es/
|
||||||
- fa: /fa/
|
- fa: /fa/
|
||||||
- fr: /fr/
|
- fr: /fr/
|
||||||
|
- he: /he/
|
||||||
- id: /id/
|
- id: /id/
|
||||||
- it: /it/
|
- it: /it/
|
||||||
- ja: /ja/
|
- ja: /ja/
|
||||||
|
|
@ -51,6 +54,7 @@ nav:
|
||||||
- pt: /pt/
|
- pt: /pt/
|
||||||
- ru: /ru/
|
- ru: /ru/
|
||||||
- sq: /sq/
|
- sq: /sq/
|
||||||
|
- sv: /sv/
|
||||||
- tr: /tr/
|
- tr: /tr/
|
||||||
- uk: /uk/
|
- uk: /uk/
|
||||||
- zh: /zh/
|
- zh: /zh/
|
||||||
|
|
@ -71,6 +75,8 @@ markdown_extensions:
|
||||||
format: !!python/name:pymdownx.superfences.fence_code_format ''
|
format: !!python/name:pymdownx.superfences.fence_code_format ''
|
||||||
- pymdownx.tabbed:
|
- pymdownx.tabbed:
|
||||||
alternate_style: true
|
alternate_style: true
|
||||||
|
- attr_list
|
||||||
|
- md_in_html
|
||||||
extra:
|
extra:
|
||||||
analytics:
|
analytics:
|
||||||
provider: google
|
provider: google
|
||||||
|
|
@ -103,6 +109,8 @@ extra:
|
||||||
name: fa
|
name: fa
|
||||||
- link: /fr/
|
- link: /fr/
|
||||||
name: fr - français
|
name: fr - français
|
||||||
|
- link: /he/
|
||||||
|
name: he
|
||||||
- link: /id/
|
- link: /id/
|
||||||
name: id
|
name: id
|
||||||
- link: /it/
|
- link: /it/
|
||||||
|
|
@ -121,6 +129,8 @@ extra:
|
||||||
name: ru - русский язык
|
name: ru - русский язык
|
||||||
- link: /sq/
|
- link: /sq/
|
||||||
name: sq - shqip
|
name: sq - shqip
|
||||||
|
- link: /sv/
|
||||||
|
name: sv - svenska
|
||||||
- link: /tr/
|
- link: /tr/
|
||||||
name: tr - Türkçe
|
name: tr - Türkçe
|
||||||
- link: /uk/
|
- link: /uk/
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ Hierdurch werden Sie nie wieder einen falschen Schlüsselnamen benutzen und spar
|
||||||
|
|
||||||
### Kompakt
|
### Kompakt
|
||||||
|
|
||||||
FastAPI nutzt für alles sinnvolle **Standard-Einstellungen**, welche optional überall konfiguriert werden können. Alle Parameter können ganz genau an Ihre Bedürfnisse angepasst werden, sodass sie genau die API definieren können, die sie brauchen.
|
FastAPI nutzt für alles sensible **Standard-Einstellungen**, welche optional überall konfiguriert werden können. Alle Parameter können ganz genau an Ihre Bedürfnisse angepasst werden, sodass sie genau die API definieren können, die sie brauchen.
|
||||||
|
|
||||||
Aber standardmäßig, **"funktioniert einfach"** alles.
|
Aber standardmäßig, **"funktioniert einfach"** alles.
|
||||||
|
|
||||||
|
|
@ -119,9 +119,9 @@ Die gesamte Validierung übernimmt das etablierte und robuste **Pydantic**.
|
||||||
|
|
||||||
### Sicherheit und Authentifizierung
|
### Sicherheit und Authentifizierung
|
||||||
|
|
||||||
Sicherheit und Authentifizierung integriert. Ohne einen Kompromiss aufgrund einer Datenbank oder den Datenentitäten.
|
Integrierte Sicherheit und Authentifizierung. Ohne Kompromisse bei Datenbanken oder Datenmodellen.
|
||||||
|
|
||||||
Unterstützt alle von OpenAPI definierten Sicherheitsschemata, hierzu gehören:
|
Unterstützt werden alle von OpenAPI definierten Sicherheitsschemata, hierzu gehören:
|
||||||
|
|
||||||
* HTTP Basis Authentifizierung.
|
* HTTP Basis Authentifizierung.
|
||||||
* **OAuth2** (auch mit **JWT Zugriffstokens**). Schauen Sie sich hierzu dieses Tutorial an: [OAuth2 mit JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
|
* **OAuth2** (auch mit **JWT Zugriffstokens**). Schauen Sie sich hierzu dieses Tutorial an: [OAuth2 mit JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
|
||||||
|
|
@ -142,8 +142,8 @@ FastAPI enthält ein extrem einfaches, aber extrem mächtiges <abbr title='oft v
|
||||||
* **Automatische Umsetzung** durch FastAPI.
|
* **Automatische Umsetzung** durch FastAPI.
|
||||||
* Alle abhängigen Komponenten könnten Daten von Anfragen, **Erweiterungen der Pfadoperations-**Einschränkungen und der automatisierten Dokumentation benötigen.
|
* Alle abhängigen Komponenten könnten Daten von Anfragen, **Erweiterungen der Pfadoperations-**Einschränkungen und der automatisierten Dokumentation benötigen.
|
||||||
* **Automatische Validierung** selbst für *Pfadoperationen*-Parameter, die in den Abhängigkeiten definiert wurden.
|
* **Automatische Validierung** selbst für *Pfadoperationen*-Parameter, die in den Abhängigkeiten definiert wurden.
|
||||||
* Unterstützt komplexe Benutzerauthentifizierungssysteme, mit **Datenbankverbindungen**, usw.
|
* Unterstützt komplexe Benutzerauthentifizierungssysteme, **Datenbankverbindungen**, usw.
|
||||||
* **Keine Kompromisse** bei Datenbanken, Eingabemasken, usw., sondern einfache Integration von allen.
|
* **Keine Kompromisse** bei Datenbanken, Eingabemasken, usw. Sondern einfache Integration von allen.
|
||||||
|
|
||||||
### Unbegrenzte Erweiterungen
|
### Unbegrenzte Erweiterungen
|
||||||
|
|
||||||
|
|
@ -165,7 +165,7 @@ Jede Integration wurde so entworfen, dass sie einfach zu nutzen ist (mit Abhäng
|
||||||
|
|
||||||
Mit **FastAPI** bekommen Sie viele von **Starlette**'s Funktionen (da FastAPI nur Starlette auf Steroiden ist):
|
Mit **FastAPI** bekommen Sie viele von **Starlette**'s Funktionen (da FastAPI nur Starlette auf Steroiden ist):
|
||||||
|
|
||||||
* Stark beeindruckende Performanz. Es ist <a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank">eines der schnellsten Python frameworks, auf Augenhöhe mit **NodeJS** und **Go**</a>.
|
* Stark beeindruckende Performanz. Es ist <a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank">eines der schnellsten Python Frameworks, auf Augenhöhe mit **NodeJS** und **Go**</a>.
|
||||||
* **WebSocket**-Unterstützung.
|
* **WebSocket**-Unterstützung.
|
||||||
* Hintergrundaufgaben im selben Prozess.
|
* Hintergrundaufgaben im selben Prozess.
|
||||||
* Ereignisse für das Starten und Herunterfahren.
|
* Ereignisse für das Starten und Herunterfahren.
|
||||||
|
|
@ -193,11 +193,11 @@ Mit **FastAPI** bekommen Sie alle Funktionen von **Pydantic** (da FastAPI für d
|
||||||
* Gutes Zusammenspiel mit Ihrer/Ihrem **<abbr title="Integrierten Entwicklungsumgebung, ähnlich zu (Quellcode-)Editor">IDE</abbr>/<abbr title="Ein Programm, was Fehler im Quellcode sucht">linter</abbr>/Gehirn**:
|
* Gutes Zusammenspiel mit Ihrer/Ihrem **<abbr title="Integrierten Entwicklungsumgebung, ähnlich zu (Quellcode-)Editor">IDE</abbr>/<abbr title="Ein Programm, was Fehler im Quellcode sucht">linter</abbr>/Gehirn**:
|
||||||
* Weil Datenstrukturen von Pydantic einfach nur Instanzen ihrer definierten Klassen sind, sollten Autovervollständigung, Linting, mypy und ihre Intuition einwandfrei funktionieren.
|
* Weil Datenstrukturen von Pydantic einfach nur Instanzen ihrer definierten Klassen sind, sollten Autovervollständigung, Linting, mypy und ihre Intuition einwandfrei funktionieren.
|
||||||
* **Schnell**:
|
* **Schnell**:
|
||||||
* In <a href="https://pydantic-docs.helpmanual.io/#benchmarks-tag" class="external-link" target="_blank">Vergleichen</a> ist Pydantic schneller als jede andere getestete Bibliothek.
|
* In <a href="https://pydantic-docs.helpmanual.io/benchmarks/" class="external-link" target="_blank">Vergleichen</a> ist Pydantic schneller als jede andere getestete Bibliothek.
|
||||||
* Validierung von **komplexen Strukturen**:
|
* Validierung von **komplexen Strukturen**:
|
||||||
* Benutzung von hierachischen Pydantic Schemata, Python `typing`’s `List` und `Dict`, etc.
|
* Benutzung von hierachischen Pydantic Schemata, Python `typing`’s `List` und `Dict`, etc.
|
||||||
* Validierungen erlauben klare und einfache Datenschemadefinition, überprüft und dokumentiert als JSON Schema.
|
* Validierungen erlauben eine klare und einfache Datenschemadefinition, überprüft und dokumentiert als JSON Schema.
|
||||||
* Sie können stark **verschachtelte JSON** Objekte haben und diese sind trotzdem validiert und annotiert.
|
* Sie können stark **verschachtelte JSON** Objekte haben und diese sind trotzdem validiert und annotiert.
|
||||||
* **Erweiterbar**:
|
* **Erweiterbar**:
|
||||||
* Pydantic erlaubt die Definition von eigenen Datentypen oder Sie können die Validierung mit einer `validator` dekorierten Methode erweitern..
|
* Pydantic erlaubt die Definition von eigenen Datentypen oder sie können die Validierung mit einer `validator` dekorierten Methode erweitern.
|
||||||
* 100% Testabdeckung.
|
* 100% Testabdeckung.
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
Python 3.6+
|
Python 3.7+
|
||||||
|
|
||||||
FastAPI stands on the shoulders of giants:
|
FastAPI stands on the shoulders of giants:
|
||||||
|
|
||||||
|
|
@ -135,7 +135,7 @@ You will also need an ASGI server, for production such as <a href="https://www.u
|
||||||
<div class="termy">
|
<div class="termy">
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ pip install uvicorn[standard]
|
$ pip install "uvicorn[standard]"
|
||||||
|
|
||||||
---> 100%
|
---> 100%
|
||||||
```
|
```
|
||||||
|
|
@ -149,7 +149,7 @@ $ pip install uvicorn[standard]
|
||||||
* Create a file `main.py` with:
|
* Create a file `main.py` with:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
from typing import Optional
|
from typing import Union
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
|
@ -162,7 +162,7 @@ def read_root():
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
def read_item(item_id: int, q: Optional[str] = None):
|
def read_item(item_id: int, q: Union[str, None] = None):
|
||||||
return {"item_id": item_id, "q": q}
|
return {"item_id": item_id, "q": q}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -172,7 +172,7 @@ def read_item(item_id: int, q: Optional[str] = None):
|
||||||
If your code uses `async` / `await`, use `async def`:
|
If your code uses `async` / `await`, use `async def`:
|
||||||
|
|
||||||
```Python hl_lines="9 14"
|
```Python hl_lines="9 14"
|
||||||
from typing import Optional
|
from typing import Union
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
|
@ -185,7 +185,7 @@ async def read_root():
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
async def read_item(item_id: int, q: Optional[str] = None):
|
async def read_item(item_id: int, q: Union[str, None] = None):
|
||||||
return {"item_id": item_id, "q": q}
|
return {"item_id": item_id, "q": q}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -264,7 +264,7 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
|
||||||
Declare the body using standard Python types, thanks to Pydantic.
|
Declare the body using standard Python types, thanks to Pydantic.
|
||||||
|
|
||||||
```Python hl_lines="4 9-12 25-27"
|
```Python hl_lines="4 9-12 25-27"
|
||||||
from typing import Optional
|
from typing import Union
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
@ -275,7 +275,7 @@ app = FastAPI()
|
||||||
class Item(BaseModel):
|
class Item(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
price: float
|
price: float
|
||||||
is_offer: Optional[bool] = None
|
is_offer: Union[bool, None] = None
|
||||||
|
|
||||||
|
|
||||||
@app.get("/")
|
@app.get("/")
|
||||||
|
|
@ -284,7 +284,7 @@ def read_root():
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
def read_item(item_id: int, q: Optional[str] = None):
|
def read_item(item_id: int, q: Union[str, None] = None):
|
||||||
return {"item_id": item_id, "q": q}
|
return {"item_id": item_id, "q": q}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,15 @@ theme:
|
||||||
name: material
|
name: material
|
||||||
custom_dir: overrides
|
custom_dir: overrides
|
||||||
palette:
|
palette:
|
||||||
- scheme: default
|
- media: '(prefers-color-scheme: light)'
|
||||||
|
scheme: default
|
||||||
primary: teal
|
primary: teal
|
||||||
accent: amber
|
accent: amber
|
||||||
toggle:
|
toggle:
|
||||||
icon: material/lightbulb
|
icon: material/lightbulb
|
||||||
name: Switch to light mode
|
name: Switch to light mode
|
||||||
- scheme: slate
|
- media: '(prefers-color-scheme: dark)'
|
||||||
|
scheme: slate
|
||||||
primary: teal
|
primary: teal
|
||||||
accent: amber
|
accent: amber
|
||||||
toggle:
|
toggle:
|
||||||
|
|
@ -42,6 +44,7 @@ nav:
|
||||||
- es: /es/
|
- es: /es/
|
||||||
- fa: /fa/
|
- fa: /fa/
|
||||||
- fr: /fr/
|
- fr: /fr/
|
||||||
|
- he: /he/
|
||||||
- id: /id/
|
- id: /id/
|
||||||
- it: /it/
|
- it: /it/
|
||||||
- ja: /ja/
|
- ja: /ja/
|
||||||
|
|
@ -51,6 +54,7 @@ nav:
|
||||||
- pt: /pt/
|
- pt: /pt/
|
||||||
- ru: /ru/
|
- ru: /ru/
|
||||||
- sq: /sq/
|
- sq: /sq/
|
||||||
|
- sv: /sv/
|
||||||
- tr: /tr/
|
- tr: /tr/
|
||||||
- uk: /uk/
|
- uk: /uk/
|
||||||
- zh: /zh/
|
- zh: /zh/
|
||||||
|
|
@ -72,6 +76,8 @@ markdown_extensions:
|
||||||
format: !!python/name:pymdownx.superfences.fence_code_format ''
|
format: !!python/name:pymdownx.superfences.fence_code_format ''
|
||||||
- pymdownx.tabbed:
|
- pymdownx.tabbed:
|
||||||
alternate_style: true
|
alternate_style: true
|
||||||
|
- attr_list
|
||||||
|
- md_in_html
|
||||||
extra:
|
extra:
|
||||||
analytics:
|
analytics:
|
||||||
provider: google
|
provider: google
|
||||||
|
|
@ -104,6 +110,8 @@ extra:
|
||||||
name: fa
|
name: fa
|
||||||
- link: /fr/
|
- link: /fr/
|
||||||
name: fr - français
|
name: fr - français
|
||||||
|
- link: /he/
|
||||||
|
name: he
|
||||||
- link: /id/
|
- link: /id/
|
||||||
name: id
|
name: id
|
||||||
- link: /it/
|
- link: /it/
|
||||||
|
|
@ -122,6 +130,8 @@ extra:
|
||||||
name: ru - русский язык
|
name: ru - русский язык
|
||||||
- link: /sq/
|
- link: /sq/
|
||||||
name: sq - shqip
|
name: sq - shqip
|
||||||
|
- link: /sv/
|
||||||
|
name: sv - svenska
|
||||||
- link: /tr/
|
- link: /tr/
|
||||||
name: tr - Türkçe
|
name: tr - Türkçe
|
||||||
- link: /uk/
|
- link: /uk/
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,17 @@
|
||||||
articles:
|
articles:
|
||||||
english:
|
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
|
||||||
|
title: Building the Poll App From Django Tutorial With FastAPI And React
|
||||||
- author: Silvan Melchior
|
- author: Silvan Melchior
|
||||||
author_link: https://github.com/silvanmelchior
|
author_link: https://github.com/silvanmelchior
|
||||||
link: https://blog.devgenius.io/seamless-fastapi-configuration-with-confz-90949c14ea12
|
link: https://blog.devgenius.io/seamless-fastapi-configuration-with-confz-90949c14ea12
|
||||||
|
|
@ -208,6 +220,10 @@ articles:
|
||||||
author_link: https://twitter.com/MantoshMukul
|
author_link: https://twitter.com/MantoshMukul
|
||||||
link: https://www.jetbrains.com/pycharm/guide/tutorials/fastapi-aws-kubernetes/
|
link: https://www.jetbrains.com/pycharm/guide/tutorials/fastapi-aws-kubernetes/
|
||||||
title: Developing FastAPI Application using K8s & AWS
|
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:
|
german:
|
||||||
- author: Nico Axtmann
|
- author: Nico Axtmann
|
||||||
author_link: https://twitter.com/_nicoax
|
author_link: https://twitter.com/_nicoax
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
sponsors:
|
sponsors:
|
||||||
- - login: cryptapi
|
- - login: jina-ai
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4
|
|
||||||
url: https://github.com/cryptapi
|
|
||||||
- login: jina-ai
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/60539444?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/60539444?v=4
|
||||||
url: https://github.com/jina-ai
|
url: https://github.com/jina-ai
|
||||||
- login: DropbaseHQ
|
- - login: Doist
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/85367855?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/2565372?v=4
|
||||||
url: https://github.com/DropbaseHQ
|
url: https://github.com/Doist
|
||||||
- - login: sushi2all
|
- login: cryptapi
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/1043732?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4
|
||||||
url: https://github.com/sushi2all
|
url: https://github.com/cryptapi
|
||||||
|
- - 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
|
- login: chaserowbotham
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/97751084?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/97751084?v=4
|
||||||
url: https://github.com/chaserowbotham
|
url: https://github.com/chaserowbotham
|
||||||
- - login: mikeckennedy
|
- - login: mikeckennedy
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/2035561?u=1bb18268bcd4d9249e1f783a063c27df9a84c05b&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/2035561?u=1bb18268bcd4d9249e1f783a063c27df9a84c05b&v=4
|
||||||
url: https://github.com/mikeckennedy
|
url: https://github.com/mikeckennedy
|
||||||
- login: Trivie
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4
|
|
||||||
url: https://github.com/Trivie
|
|
||||||
- login: deta
|
- login: deta
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/47275976?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/47275976?v=4
|
||||||
url: https://github.com/deta
|
url: https://github.com/deta
|
||||||
|
|
@ -32,18 +32,18 @@ sponsors:
|
||||||
- login: VincentParedes
|
- login: VincentParedes
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/103889729?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/103889729?v=4
|
||||||
url: https://github.com/VincentParedes
|
url: https://github.com/VincentParedes
|
||||||
- - login: plocher
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/1082871?v=4
|
|
||||||
url: https://github.com/plocher
|
|
||||||
- - login: InesIvanova
|
- - login: InesIvanova
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/22920417?u=409882ec1df6dbd77455788bb383a8de223dbf6f&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/22920417?u=409882ec1df6dbd77455788bb383a8de223dbf6f&v=4
|
||||||
url: https://github.com/InesIvanova
|
url: https://github.com/InesIvanova
|
||||||
- - login: SendCloud
|
- - login: zopyx
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/594239?u=8e5ce882664f47fd61002bed51718c78c3799d24&v=4
|
||||||
|
url: https://github.com/zopyx
|
||||||
|
- login: SendCloud
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/7831959?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/7831959?v=4
|
||||||
url: https://github.com/SendCloud
|
url: https://github.com/SendCloud
|
||||||
- login: qaas
|
- login: mercedes-benz
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/8503759?u=10a6b4391ad6ab4cf9487ce54e3fcb61322d1efc&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4
|
||||||
url: https://github.com/qaas
|
url: https://github.com/mercedes-benz
|
||||||
- login: xoflare
|
- login: xoflare
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/74335107?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/74335107?v=4
|
||||||
url: https://github.com/xoflare
|
url: https://github.com/xoflare
|
||||||
|
|
@ -59,6 +59,9 @@ sponsors:
|
||||||
- login: HiredScore
|
- login: HiredScore
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/3908850?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/3908850?v=4
|
||||||
url: https://github.com/HiredScore
|
url: https://github.com/HiredScore
|
||||||
|
- login: Trivie
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4
|
||||||
|
url: https://github.com/Trivie
|
||||||
- login: wdwinslow
|
- login: wdwinslow
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4
|
||||||
url: https://github.com/wdwinslow
|
url: https://github.com/wdwinslow
|
||||||
|
|
@ -68,22 +71,31 @@ sponsors:
|
||||||
- login: RodneyU215
|
- login: RodneyU215
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/3329665?u=ec6a9adf8e7e8e306eed7d49687c398608d1604f&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/3329665?u=ec6a9adf8e7e8e306eed7d49687c398608d1604f&v=4
|
||||||
url: https://github.com/RodneyU215
|
url: https://github.com/RodneyU215
|
||||||
- login: grillazz
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=0b32b7073ae1ab8b7f6d2db0188c2e1e357ff451&v=4
|
|
||||||
url: https://github.com/grillazz
|
|
||||||
- login: tizz98
|
- login: tizz98
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/5739698?u=f095a3659e3a8e7c69ccd822696990b521ea25f9&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/5739698?u=f095a3659e3a8e7c69ccd822696990b521ea25f9&v=4
|
||||||
url: https://github.com/tizz98
|
url: https://github.com/tizz98
|
||||||
|
- login: Vikka
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/9381120?u=4bfc7032a824d1ed1994aa8256dfa597c8f187ad&v=4
|
||||||
|
url: https://github.com/Vikka
|
||||||
- login: jmaralc
|
- login: jmaralc
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/21101214?u=b15a9f07b7cbf6c9dcdbcb6550bbd2c52f55aa50&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/21101214?u=b15a9f07b7cbf6c9dcdbcb6550bbd2c52f55aa50&v=4
|
||||||
url: https://github.com/jmaralc
|
url: https://github.com/jmaralc
|
||||||
- login: marutoraman
|
- login: takashi-yoneya
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4
|
||||||
url: https://github.com/marutoraman
|
url: https://github.com/takashi-yoneya
|
||||||
- login: mainframeindustries
|
- login: mainframeindustries
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4
|
||||||
url: https://github.com/mainframeindustries
|
url: https://github.com/mainframeindustries
|
||||||
- login: A-Edge
|
- login: DelfinaCare
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4
|
||||||
|
url: https://github.com/DelfinaCare
|
||||||
|
- - login: povilasb
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/1213442?u=b11f58ed6ceea6e8297c9b310030478ebdac894d&v=4
|
||||||
|
url: https://github.com/povilasb
|
||||||
|
- login: primer-io
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4
|
||||||
|
url: https://github.com/primer-io
|
||||||
|
- - login: A-Edge
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4
|
||||||
url: https://github.com/A-Edge
|
url: https://github.com/A-Edge
|
||||||
- - login: Kludex
|
- - login: Kludex
|
||||||
|
|
@ -92,18 +104,21 @@ sponsors:
|
||||||
- login: samuelcolvin
|
- login: samuelcolvin
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=807390ba9cfe23906c3bf8a0d56aaca3cf2bfa0d&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=807390ba9cfe23906c3bf8a0d56aaca3cf2bfa0d&v=4
|
||||||
url: https://github.com/samuelcolvin
|
url: https://github.com/samuelcolvin
|
||||||
- login: jokull
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/701?u=0532b62166893d5160ef795c4c8b7512d971af05&v=4
|
|
||||||
url: https://github.com/jokull
|
|
||||||
- login: jefftriplett
|
- login: jefftriplett
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/50527?u=af1ddfd50f6afd6d99f333ba2ac8d0a5b245ea74&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/50527?u=af1ddfd50f6afd6d99f333ba2ac8d0a5b245ea74&v=4
|
||||||
url: https://github.com/jefftriplett
|
url: https://github.com/jefftriplett
|
||||||
|
- login: medecau
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/59870?u=f9341c95adaba780828162fd4c7442357ecfcefa&v=4
|
||||||
|
url: https://github.com/medecau
|
||||||
- login: kamalgill
|
- login: kamalgill
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/133923?u=0df9181d97436ce330e9acf90ab8a54b7022efe7&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/133923?u=0df9181d97436ce330e9acf90ab8a54b7022efe7&v=4
|
||||||
url: https://github.com/kamalgill
|
url: https://github.com/kamalgill
|
||||||
- login: jsutton
|
- login: dekoza
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/280777?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/210980?u=c03c78a8ae1039b500dfe343665536ebc51979b2&v=4
|
||||||
url: https://github.com/jsutton
|
url: https://github.com/dekoza
|
||||||
|
- login: pamelafox
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/297042?v=4
|
||||||
|
url: https://github.com/pamelafox
|
||||||
- login: deserat
|
- login: deserat
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/299332?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/299332?v=4
|
||||||
url: https://github.com/deserat
|
url: https://github.com/deserat
|
||||||
|
|
@ -116,15 +131,21 @@ sponsors:
|
||||||
- login: koxudaxi
|
- login: koxudaxi
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4
|
||||||
url: https://github.com/koxudaxi
|
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
|
- login: jqueguiner
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/690878?u=e4835b2a985a0f2d52018e4926cb5a58c26a62e8&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/690878?u=bd65cc1f228ce6455e56dfaca3ef47c33bc7c3b0&v=4
|
||||||
url: https://github.com/jqueguiner
|
url: https://github.com/jqueguiner
|
||||||
|
- login: alexsantos
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/932219?v=4
|
||||||
|
url: https://github.com/alexsantos
|
||||||
|
- login: tcsmith
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/989034?u=7d8d741552b3279e8f4d3878679823a705a46f8f&v=4
|
||||||
|
url: https://github.com/tcsmith
|
||||||
- login: ltieman
|
- login: ltieman
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/1084689?u=e69b17de17cb3ca141a17daa7ccbe173ceb1eb17&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/1084689?u=e69b17de17cb3ca141a17daa7ccbe173ceb1eb17&v=4
|
||||||
url: https://github.com/ltieman
|
url: https://github.com/ltieman
|
||||||
- login: westonsteimel
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/1593939?u=0f2c0e3647f916fe295d62fa70da7a4c177115e3&v=4
|
|
||||||
url: https://github.com/westonsteimel
|
|
||||||
- login: corleyma
|
- login: corleyma
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/2080732?u=aed2ff652294a87d666b1c3f6dbe98104db76d26&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/2080732?u=aed2ff652294a87d666b1c3f6dbe98104db76d26&v=4
|
||||||
url: https://github.com/corleyma
|
url: https://github.com/corleyma
|
||||||
|
|
@ -140,18 +161,33 @@ sponsors:
|
||||||
- login: Shark009
|
- login: Shark009
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/3163309?u=0c6f4091b0eda05c44c390466199826e6dc6e431&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/3163309?u=0c6f4091b0eda05c44c390466199826e6dc6e431&v=4
|
||||||
url: https://github.com/Shark009
|
url: https://github.com/Shark009
|
||||||
|
- login: grillazz
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=0b32b7073ae1ab8b7f6d2db0188c2e1e357ff451&v=4
|
||||||
|
url: https://github.com/grillazz
|
||||||
- login: dblackrun
|
- login: dblackrun
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/3528486?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/3528486?v=4
|
||||||
url: https://github.com/dblackrun
|
url: https://github.com/dblackrun
|
||||||
- login: zsinx6
|
- login: zsinx6
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4
|
||||||
url: https://github.com/zsinx6
|
url: https://github.com/zsinx6
|
||||||
|
- 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: anomaly
|
- login: anomaly
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4
|
||||||
url: https://github.com/anomaly
|
url: https://github.com/anomaly
|
||||||
- login: peterHoburg
|
- login: peterHoburg
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/3860655?u=f55f47eb2d6a9b495e806ac5a044e3ae01ccc1fa&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/3860655?u=f55f47eb2d6a9b495e806ac5a044e3ae01ccc1fa&v=4
|
||||||
url: https://github.com/peterHoburg
|
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
|
||||||
- login: jaredtrog
|
- login: jaredtrog
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4
|
||||||
url: https://github.com/jaredtrog
|
url: https://github.com/jaredtrog
|
||||||
|
|
@ -167,14 +203,11 @@ sponsors:
|
||||||
- login: ennui93
|
- login: ennui93
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/5300907?u=5b5452725ddb391b2caaebf34e05aba873591c3a&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/5300907?u=5b5452725ddb391b2caaebf34e05aba873591c3a&v=4
|
||||||
url: https://github.com/ennui93
|
url: https://github.com/ennui93
|
||||||
- login: MacroPower
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/5648814?u=e13991efd1e03c44c911f919872e750530ded633&v=4
|
|
||||||
url: https://github.com/MacroPower
|
|
||||||
- login: Yaleesa
|
- login: Yaleesa
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/6135475?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/6135475?v=4
|
||||||
url: https://github.com/Yaleesa
|
url: https://github.com/Yaleesa
|
||||||
- login: iwpnd
|
- 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
|
url: https://github.com/iwpnd
|
||||||
- login: simw
|
- login: simw
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/6322526?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/6322526?v=4
|
||||||
|
|
@ -194,12 +227,12 @@ sponsors:
|
||||||
- login: Shackelford-Arden
|
- login: Shackelford-Arden
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/7362263?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/7362263?v=4
|
||||||
url: https://github.com/Shackelford-Arden
|
url: https://github.com/Shackelford-Arden
|
||||||
- login: Vikka
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/9381120?u=4bfc7032a824d1ed1994aa8256dfa597c8f187ad&v=4
|
|
||||||
url: https://github.com/Vikka
|
|
||||||
- login: Ge0f3
|
- login: Ge0f3
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/11887760?u=ccd80f1ac36dcb8517ef5c4e702e8cc5a80cad2f&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/11887760?u=ccd80f1ac36dcb8517ef5c4e702e8cc5a80cad2f&v=4
|
||||||
url: https://github.com/Ge0f3
|
url: https://github.com/Ge0f3
|
||||||
|
- login: svats2k
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/12378398?u=ecf28c19f61052e664bdfeb2391f8107d137915c&v=4
|
||||||
|
url: https://github.com/svats2k
|
||||||
- login: gokulyc
|
- login: gokulyc
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/13468848?u=269f269d3e70407b5fb80138c52daba7af783997&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/13468848?u=269f269d3e70407b5fb80138c52daba7af783997&v=4
|
||||||
url: https://github.com/gokulyc
|
url: https://github.com/gokulyc
|
||||||
|
|
@ -215,12 +248,6 @@ sponsors:
|
||||||
- login: wedwardbeck
|
- login: wedwardbeck
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/19333237?u=1de4ae2bf8d59eb4c013f21d863cbe0f2010575f&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/19333237?u=1de4ae2bf8d59eb4c013f21d863cbe0f2010575f&v=4
|
||||||
url: https://github.com/wedwardbeck
|
url: https://github.com/wedwardbeck
|
||||||
- login: linusg
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/19366641?u=125e390abef8fff3b3b0d370c369cba5d7fd4c67&v=4
|
|
||||||
url: https://github.com/linusg
|
|
||||||
- login: stradivari96
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/19752586?u=255f5f06a768f518b20cebd6963e840ac49294fd&v=4
|
|
||||||
url: https://github.com/stradivari96
|
|
||||||
- login: RedCarpetUp
|
- login: RedCarpetUp
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/20360440?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/20360440?v=4
|
||||||
url: https://github.com/RedCarpetUp
|
url: https://github.com/RedCarpetUp
|
||||||
|
|
@ -230,6 +257,9 @@ sponsors:
|
||||||
- login: shuheng-liu
|
- login: shuheng-liu
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/22414322?u=813c45f30786c6b511b21a661def025d8f7b609e&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/22414322?u=813c45f30786c6b511b21a661def025d8f7b609e&v=4
|
||||||
url: https://github.com/shuheng-liu
|
url: https://github.com/shuheng-liu
|
||||||
|
- login: Joeriksson
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/25037079?v=4
|
||||||
|
url: https://github.com/Joeriksson
|
||||||
- login: cometa-haley
|
- login: cometa-haley
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=cec1a3e0643b785288ae8260cc295a85ab344995&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=cec1a3e0643b785288ae8260cc295a85ab344995&v=4
|
||||||
url: https://github.com/cometa-haley
|
url: https://github.com/cometa-haley
|
||||||
|
|
@ -239,63 +269,66 @@ sponsors:
|
||||||
- login: veprimk
|
- login: veprimk
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/29689749?u=f8cb5a15a286e522e5b189bc572d5a1a90217fb2&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/29689749?u=f8cb5a15a286e522e5b189bc572d5a1a90217fb2&v=4
|
||||||
url: https://github.com/veprimk
|
url: https://github.com/veprimk
|
||||||
- login: meysam81
|
- login: BrettskiPy
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/30233243?u=64dc9fc62d039892c6fb44d804251cad5537132b&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/30988215?u=d8a94a67e140d5ee5427724b292cc52d8827087a&v=4
|
||||||
url: https://github.com/meysam81
|
url: https://github.com/BrettskiPy
|
||||||
- login: mauroalejandrojm
|
- login: mauroalejandrojm
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/31569442?u=cdada990a1527926a36e95f62c30a8b48bbc49a1&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/31569442?u=cdada990a1527926a36e95f62c30a8b48bbc49a1&v=4
|
||||||
url: https://github.com/mauroalejandrojm
|
url: https://github.com/mauroalejandrojm
|
||||||
- login: Leay15
|
- login: Leay15
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4
|
||||||
url: https://github.com/Leay15
|
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
|
- login: AlrasheedA
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/33544979?u=7fe66bf62b47682612b222e3e8f4795ef3be769b&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/33544979?u=7fe66bf62b47682612b222e3e8f4795ef3be769b&v=4
|
||||||
url: https://github.com/AlrasheedA
|
url: https://github.com/AlrasheedA
|
||||||
- login: ProteinQure
|
- login: ProteinQure
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4
|
||||||
url: https://github.com/ProteinQure
|
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
|
- login: ybressler
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=6621dc9ab53b697912ab2a32211bb29ae90a9112&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=41e2c00f1eebe3c402635f0325e41b4e6511462c&v=4
|
||||||
url: https://github.com/ybressler
|
url: https://github.com/ybressler
|
||||||
- login: iamkarshe
|
- login: ddilidili
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/43641892?u=d08c901b359c931784501740610d416558ff3e24&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/42176885?u=c0a849dde06987434653197b5f638d3deb55fc6c&v=4
|
||||||
url: https://github.com/iamkarshe
|
url: https://github.com/ddilidili
|
||||||
- login: dbanty
|
- login: VictorCalderon
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9bcce836bbce55835291c5b2ac93a4e311f4b3c3&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/44529243?u=cea69884f826a29aff1415493405209e0706d07a&v=4
|
||||||
url: https://github.com/dbanty
|
url: https://github.com/VictorCalderon
|
||||||
|
- login: arthuRHD
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/48015496?u=05a0d5b8b9320eeb7990d35c9337b823f269d2ff&v=4
|
||||||
|
url: https://github.com/arthuRHD
|
||||||
- login: rafsaf
|
- login: rafsaf
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=be9f06b8ced2d2b677297decc781fa8ce4f7ddbd&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4
|
||||||
url: https://github.com/rafsaf
|
url: https://github.com/rafsaf
|
||||||
|
- login: yezz123
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
|
||||||
|
url: https://github.com/yezz123
|
||||||
- login: dudikbender
|
- login: dudikbender
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=494f85229115076121b3639a3806bbac1c6ae7f6&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=494f85229115076121b3639a3806bbac1c6ae7f6&v=4
|
||||||
url: https://github.com/dudikbender
|
url: https://github.com/dudikbender
|
||||||
- login: daisuke8000
|
- login: llamington
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/55035595?u=5025e379cd3655ae1a96039efc85223a873d2e38&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/54869395?u=42ea59b76f49449f41a4d106bb65a130797e8d7c&v=4
|
||||||
url: https://github.com/daisuke8000
|
url: https://github.com/llamington
|
||||||
- login: yakkonaut
|
- login: yakkonaut
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/60633704?u=90a71fd631aa998ba4a96480788f017c9904e07b&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/60633704?u=90a71fd631aa998ba4a96480788f017c9904e07b&v=4
|
||||||
url: https://github.com/yakkonaut
|
url: https://github.com/yakkonaut
|
||||||
- login: primer-io
|
- login: patsatsia
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=419516384f798a35e9d9e2dd81282cc46c151b58&v=4
|
||||||
url: https://github.com/primer-io
|
url: https://github.com/patsatsia
|
||||||
- login: around
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/62425723?v=4
|
|
||||||
url: https://github.com/around
|
|
||||||
- login: predictionmachine
|
- login: predictionmachine
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/63719559?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/63719559?v=4
|
||||||
url: https://github.com/predictionmachine
|
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
|
- login: daverin
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/70378377?u=6d1814195c0de7162820eaad95a25b423a3869c0&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/70378377?u=6d1814195c0de7162820eaad95a25b423a3869c0&v=4
|
||||||
url: https://github.com/daverin
|
url: https://github.com/daverin
|
||||||
- login: anthonycepeda
|
- login: anthonycepeda
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=892f700c79f9732211bd5221bf16eec32356a732&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=4252c6b6dc5024af502a823a3ac5e7a03a69963f&v=4
|
||||||
url: https://github.com/anthonycepeda
|
url: https://github.com/anthonycepeda
|
||||||
- login: NinaHwang
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
|
|
||||||
url: https://github.com/NinaHwang
|
|
||||||
- login: dotlas
|
- login: dotlas
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/88832003?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/88832003?v=4
|
||||||
url: https://github.com/dotlas
|
url: https://github.com/dotlas
|
||||||
|
|
@ -306,7 +339,7 @@ sponsors:
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/46711?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/46711?v=4
|
||||||
url: https://github.com/linux-china
|
url: https://github.com/linux-china
|
||||||
- login: ddanier
|
- 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
|
url: https://github.com/ddanier
|
||||||
- login: jhb
|
- login: jhb
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/142217?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/142217?v=4
|
||||||
|
|
@ -317,8 +350,11 @@ sponsors:
|
||||||
- login: bryanculbertson
|
- login: bryanculbertson
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/144028?u=defda4f90e93429221cc667500944abde60ebe4a&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/144028?u=defda4f90e93429221cc667500944abde60ebe4a&v=4
|
||||||
url: https://github.com/bryanculbertson
|
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
|
- 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
|
url: https://github.com/yourkin
|
||||||
- login: slafs
|
- login: slafs
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4
|
||||||
|
|
@ -336,41 +372,38 @@ sponsors:
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/388564?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/388564?v=4
|
||||||
url: https://github.com/dmig
|
url: https://github.com/dmig
|
||||||
- login: rinckd
|
- 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
|
url: https://github.com/rinckd
|
||||||
- login: securancy
|
- login: securancy
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/606673?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/606673?v=4
|
||||||
url: https://github.com/securancy
|
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
|
- login: hardbyte
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/855189?u=aa29e92f34708814d6b67fcd47ca4cf2ce1c04ed&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/855189?u=aa29e92f34708814d6b67fcd47ca4cf2ce1c04ed&v=4
|
||||||
url: https://github.com/hardbyte
|
url: https://github.com/hardbyte
|
||||||
|
- login: browniebroke
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4
|
||||||
|
url: https://github.com/browniebroke
|
||||||
- login: janfilips
|
- 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
|
url: https://github.com/janfilips
|
||||||
- login: scari
|
- login: woodrad
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/964251?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/1410765?u=86707076bb03d143b3b11afc1743d2aa496bd8bf&v=4
|
||||||
url: https://github.com/scari
|
url: https://github.com/woodrad
|
||||||
- login: Pytlicek
|
- 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
|
url: https://github.com/Pytlicek
|
||||||
- login: Celeborn2BeAlive
|
- login: allen0125
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/1659465?u=944517e4db0f6df65070074e81cabdad9c8a434b&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/1448456?u=dc2ad819497eef494b88688a1796e0adb87e7cae&v=4
|
||||||
url: https://github.com/Celeborn2BeAlive
|
url: https://github.com/allen0125
|
||||||
- login: WillHogan
|
- login: WillHogan
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=7036c064cf29781470573865264ec8e60b6b809f&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=7036c064cf29781470573865264ec8e60b6b809f&v=4
|
||||||
url: https://github.com/WillHogan
|
url: https://github.com/WillHogan
|
||||||
- login: cbonoz
|
- login: cbonoz
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/2351087?u=fd3e8030b2cc9fbfbb54a65e9890c548a016f58b&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/2351087?u=fd3e8030b2cc9fbfbb54a65e9890c548a016f58b&v=4
|
||||||
url: https://github.com/cbonoz
|
url: https://github.com/cbonoz
|
||||||
- login: Abbe98
|
- login: Debakel
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/2631719?u=8a064aba9a710229ad28c616549d81a24191a5df&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/2857237?u=07df6d11c8feef9306d071cb1c1005a2dd596585&v=4
|
||||||
url: https://github.com/Abbe98
|
url: https://github.com/Debakel
|
||||||
- login: rglsk
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/2768101?u=e349c88673f2155fe021331377c656a9d74bcc25&v=4
|
|
||||||
url: https://github.com/rglsk
|
|
||||||
- login: paul121
|
- login: paul121
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/3116995?u=6e2d8691cc345e63ee02e4eb4d7cef82b1fcbedc&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/3116995?u=6e2d8691cc345e63ee02e4eb4d7cef82b1fcbedc&v=4
|
||||||
url: https://github.com/paul121
|
url: https://github.com/paul121
|
||||||
|
|
@ -380,30 +413,36 @@ sponsors:
|
||||||
- login: anthonycorletti
|
- login: anthonycorletti
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/3477132?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/3477132?v=4
|
||||||
url: https://github.com/anthonycorletti
|
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
|
- login: pawamoy
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4
|
||||||
url: https://github.com/pawamoy
|
url: https://github.com/pawamoy
|
||||||
- login: Alisa-lisa
|
- login: Alisa-lisa
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4
|
||||||
url: https://github.com/Alisa-lisa
|
url: https://github.com/Alisa-lisa
|
||||||
|
- login: danielunderwood
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4
|
||||||
|
url: https://github.com/danielunderwood
|
||||||
- login: unredundant
|
- login: unredundant
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/5607577?u=57dd0023365bec03f4fc566df6b81bc0a264a47d&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/5607577?u=57dd0023365bec03f4fc566df6b81bc0a264a47d&v=4
|
||||||
url: https://github.com/unredundant
|
url: https://github.com/unredundant
|
||||||
|
- login: Baghdady92
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/5708590?v=4
|
||||||
|
url: https://github.com/Baghdady92
|
||||||
- login: holec
|
- login: holec
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/6438041?u=f5af71ec85b3a9d7b8139cb5af0512b02fa9ab1e&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/6438041?u=f5af71ec85b3a9d7b8139cb5af0512b02fa9ab1e&v=4
|
||||||
url: https://github.com/holec
|
url: https://github.com/holec
|
||||||
|
- login: hcristea
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/7814406?u=61d7a4fcf846983a4606788eac25e1c6c1209ba8&v=4
|
||||||
|
url: https://github.com/hcristea
|
||||||
- login: moonape1226
|
- login: moonape1226
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4
|
||||||
url: https://github.com/moonape1226
|
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
|
- login: yenchenLiu
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/9199638?u=8cdf5ae507448430d90f6f3518d1665a23afe99b&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/9199638?u=8cdf5ae507448430d90f6f3518d1665a23afe99b&v=4
|
||||||
url: https://github.com/yenchenLiu
|
url: https://github.com/yenchenLiu
|
||||||
- login: VivianSolide
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/9358572?u=4a38ef72dd39e8b262bd5ab819992128b55c52b4&v=4
|
|
||||||
url: https://github.com/VivianSolide
|
|
||||||
- login: xncbf
|
- login: xncbf
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=866a1311e4bd3ec5ae84185c4fcc99f397c883d7&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=866a1311e4bd3ec5ae84185c4fcc99f397c883d7&v=4
|
||||||
url: https://github.com/xncbf
|
url: https://github.com/xncbf
|
||||||
|
|
@ -416,21 +455,39 @@ sponsors:
|
||||||
- login: satwikkansal
|
- login: satwikkansal
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/10217535?u=b12d6ef74ea297de9e46da6933b1a5b7ba9e6a61&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/10217535?u=b12d6ef74ea297de9e46da6933b1a5b7ba9e6a61&v=4
|
||||||
url: https://github.com/satwikkansal
|
url: https://github.com/satwikkansal
|
||||||
|
- login: mntolia
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/10390224?v=4
|
||||||
|
url: https://github.com/mntolia
|
||||||
- login: pheanex
|
- login: pheanex
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/10408624?u=5b6bab6ee174aa6e991333e06eb29f628741013d&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/10408624?u=5b6bab6ee174aa6e991333e06eb29f628741013d&v=4
|
||||||
url: https://github.com/pheanex
|
url: https://github.com/pheanex
|
||||||
- login: JimFawkes
|
- login: JimFawkes
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/12075115?u=dc58ecfd064d72887c34bf500ddfd52592509acd&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/12075115?u=dc58ecfd064d72887c34bf500ddfd52592509acd&v=4
|
||||||
url: https://github.com/JimFawkes
|
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
|
- login: logan-connolly
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/16244943?u=8ae66dfbba936463cc8aa0dd7a6d2b4c0cc757eb&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/16244943?u=8ae66dfbba936463cc8aa0dd7a6d2b4c0cc757eb&v=4
|
||||||
url: https://github.com/logan-connolly
|
url: https://github.com/logan-connolly
|
||||||
|
- login: sanghunka
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/16280020?u=7d8fafd8bfe6d7900bb1e52d5a5d5da0c02bc164&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
|
- login: cdsre
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/16945936?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/16945936?v=4
|
||||||
url: https://github.com/cdsre
|
url: https://github.com/cdsre
|
||||||
- login: jangia
|
- login: jangia
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/17927101?u=9261b9bb0c3e3bb1ecba43e8915dc58d8c9a077e&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/17927101?u=9261b9bb0c3e3bb1ecba43e8915dc58d8c9a077e&v=4
|
||||||
url: https://github.com/jangia
|
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
|
||||||
- login: ghandic
|
- login: ghandic
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4
|
||||||
url: https://github.com/ghandic
|
url: https://github.com/ghandic
|
||||||
|
|
@ -440,57 +497,87 @@ sponsors:
|
||||||
- login: mertguvencli
|
- login: mertguvencli
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/29762151?u=16a906d90df96c8cff9ea131a575c4bc171b1523&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/29762151?u=16a906d90df96c8cff9ea131a575c4bc171b1523&v=4
|
||||||
url: https://github.com/mertguvencli
|
url: https://github.com/mertguvencli
|
||||||
- login: dwreeves
|
- login: ruizdiazever
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/31971762?u=69732aba05aa5cf0780866349ebe109cf632b047&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/29817086?u=2df54af55663d246e3a4dc8273711c37f1adb117&v=4
|
||||||
url: https://github.com/dwreeves
|
url: https://github.com/ruizdiazever
|
||||||
- login: kitaramu0401
|
- login: HosamAlmoghraby
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/33246506?u=929e6efa2c518033b8097ba524eb5347a069bb3b&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/32025281?u=aa1b09feabccbf9dc506b81c71155f32d126cefa&v=4
|
||||||
url: https://github.com/kitaramu0401
|
url: https://github.com/HosamAlmoghraby
|
||||||
- login: engineerjoe440
|
- login: engineerjoe440
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4
|
||||||
url: https://github.com/engineerjoe440
|
url: https://github.com/engineerjoe440
|
||||||
- login: declon
|
- login: declon
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/36180226?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/36180226?v=4
|
||||||
url: https://github.com/declon
|
url: https://github.com/declon
|
||||||
|
- login: alvarobartt
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/36760800?u=9b38695807eb981d452989699ff72ec2d8f6508e&v=4
|
||||||
|
url: https://github.com/alvarobartt
|
||||||
- login: d-e-h-i-o
|
- login: d-e-h-i-o
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/36816716?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/36816716?v=4
|
||||||
url: https://github.com/d-e-h-i-o
|
url: https://github.com/d-e-h-i-o
|
||||||
|
- login: ww-daniel-mora
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/38921751?u=ae14bc1e40f2dd5a9c5741fc0b0dffbd416a5fa9&v=4
|
||||||
|
url: https://github.com/ww-daniel-mora
|
||||||
|
- login: rwxd
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=9ddf8023ca3326381ba8fb77285ae36598a15de3&v=4
|
||||||
|
url: https://github.com/rwxd
|
||||||
- login: ilias-ant
|
- login: ilias-ant
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/42189572?u=a2d6121bac4d125d92ec207460fa3f1842d37e66&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/42189572?u=a2d6121bac4d125d92ec207460fa3f1842d37e66&v=4
|
||||||
url: https://github.com/ilias-ant
|
url: https://github.com/ilias-ant
|
||||||
- login: arrrrrmin
|
- 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
|
url: https://github.com/arrrrrmin
|
||||||
- login: Nephilim-Jack
|
- login: MauriceKuenicke
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/48372168?u=6f2bb405238d7efc467536fe01f58df6779c58a9&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/47433175?u=37455bc95c7851db296ac42626f0cacb77ca2443&v=4
|
||||||
url: https://github.com/Nephilim-Jack
|
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
|
- login: akanz1
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/51492342?u=2280f57134118714645e16b535c1a37adf6b369b&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/51492342?u=2280f57134118714645e16b535c1a37adf6b369b&v=4
|
||||||
url: https://github.com/akanz1
|
url: https://github.com/akanz1
|
||||||
- login: rooflexx
|
- login: shidenko97
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/58993673?u=f8ba450460f1aea18430ed1e4a3889049a3b4dfa&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/54946990?u=3fdc0caea36af9217dacf1cc7760c7ed9d67dcfe&v=4
|
||||||
url: https://github.com/rooflexx
|
url: https://github.com/shidenko97
|
||||||
- login: denisyao1
|
- login: data-djinn
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/60019356?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/56449985?u=42146e140806908d49bd59ccc96f222abf587886&v=4
|
||||||
url: https://github.com/denisyao1
|
url: https://github.com/data-djinn
|
||||||
|
- login: leo-jp-edwards
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/58213433?u=2c128e8b0794b7a66211cd7d8ebe05db20b7e9c0&v=4
|
||||||
|
url: https://github.com/leo-jp-edwards
|
||||||
- login: apar-tiwari
|
- login: apar-tiwari
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/61064197?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/61064197?v=4
|
||||||
url: https://github.com/apar-tiwari
|
url: https://github.com/apar-tiwari
|
||||||
|
- login: Vyvy-vi
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/62864373?u=1a9b0b28779abc2bc9b62cb4d2e44d453973c9c3&v=4
|
||||||
|
url: https://github.com/Vyvy-vi
|
||||||
- login: 0417taehyun
|
- login: 0417taehyun
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4
|
||||||
url: https://github.com/0417taehyun
|
url: https://github.com/0417taehyun
|
||||||
|
- login: realabja
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/66185192?u=001e2dd9297784f4218997981b4e6fa8357bb70b&v=4
|
||||||
|
url: https://github.com/realabja
|
||||||
- login: alessio-proietti
|
- login: alessio-proietti
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/67370599?u=8ac73db1e18e946a7681f173abdb640516f88515&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/67370599?u=8ac73db1e18e946a7681f173abdb640516f88515&v=4
|
||||||
url: https://github.com/alessio-proietti
|
url: https://github.com/alessio-proietti
|
||||||
- - login: backbord
|
- login: pondDevThai
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/6814946?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/71592181?u=08af9a59bccfd8f6b101de1005aa9822007d0a44&v=4
|
||||||
url: https://github.com/backbord
|
url: https://github.com/pondDevThai
|
||||||
- login: sadikkuzu
|
- - login: mattwelke
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=765ed469c44c004560079210ccdad5b29938eaa9&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/7719209?u=5d963ead289969257190b133250653bd99df06ba&v=4
|
||||||
url: https://github.com/sadikkuzu
|
url: https://github.com/mattwelke
|
||||||
|
- login: cesarfreire
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/21126103?u=5d428f77f9b63c741f0e9ca5e15a689017b66fe8&v=4
|
||||||
|
url: https://github.com/cesarfreire
|
||||||
- login: gabrielmbmb
|
- login: gabrielmbmb
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=6d1e00b5d558e96718312ff910a2318f47cc3145&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=6d1e00b5d558e96718312ff910a2318f47cc3145&v=4
|
||||||
url: https://github.com/gabrielmbmb
|
url: https://github.com/gabrielmbmb
|
||||||
- login: danburonline
|
- login: danburonline
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/34251194?u=2cad4388c1544e539ecb732d656e42fb07b4ff2d&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/34251194?u=2cad4388c1544e539ecb732d656e42fb07b4ff2d&v=4
|
||||||
url: https://github.com/danburonline
|
url: https://github.com/danburonline
|
||||||
|
- login: Moises6669
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/66188523?u=96af25b8d5be9f983cb96e9dd7c605c716caf1f5&v=4
|
||||||
|
url: https://github.com/Moises6669
|
||||||
|
- login: zahariev-webbersof
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/68993494?u=b341c94a8aa0624e05e201bcf8ae5b2697e3be2f&v=4
|
||||||
|
url: https://github.com/zahariev-webbersof
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
maintainers:
|
maintainers:
|
||||||
- login: tiangolo
|
- login: tiangolo
|
||||||
answers: 1243
|
answers: 1271
|
||||||
prs: 300
|
prs: 338
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=5cad72c846b7aba2e960546af490edc7375dafc4&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=740f11212a731f56798f558ceddb0bd07642afa7&v=4
|
||||||
url: https://github.com/tiangolo
|
url: https://github.com/tiangolo
|
||||||
experts:
|
experts:
|
||||||
- login: Kludex
|
- login: Kludex
|
||||||
count: 335
|
count: 364
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||||
url: https://github.com/Kludex
|
url: https://github.com/Kludex
|
||||||
- login: dmontagu
|
- login: dmontagu
|
||||||
|
|
@ -15,7 +15,7 @@ experts:
|
||||||
url: https://github.com/dmontagu
|
url: https://github.com/dmontagu
|
||||||
- login: ycd
|
- login: ycd
|
||||||
count: 221
|
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
|
url: https://github.com/ycd
|
||||||
- login: Mause
|
- login: Mause
|
||||||
count: 207
|
count: 207
|
||||||
|
|
@ -25,50 +25,62 @@ experts:
|
||||||
count: 166
|
count: 166
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
|
||||||
url: https://github.com/euri10
|
url: https://github.com/euri10
|
||||||
|
- login: JarroVGIT
|
||||||
|
count: 163
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
|
||||||
|
url: https://github.com/JarroVGIT
|
||||||
- login: phy25
|
- login: phy25
|
||||||
count: 130
|
count: 130
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4
|
||||||
url: https://github.com/phy25
|
url: https://github.com/phy25
|
||||||
- login: raphaelauv
|
- login: raphaelauv
|
||||||
count: 71
|
count: 77
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
|
||||||
url: https://github.com/raphaelauv
|
url: https://github.com/raphaelauv
|
||||||
- login: ArcLightSlavik
|
- login: ArcLightSlavik
|
||||||
count: 71
|
count: 71
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
|
||||||
url: https://github.com/ArcLightSlavik
|
url: https://github.com/ArcLightSlavik
|
||||||
|
- login: iudeen
|
||||||
|
count: 65
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
|
||||||
|
url: https://github.com/iudeen
|
||||||
- login: falkben
|
- login: falkben
|
||||||
count: 58
|
count: 58
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
|
||||||
url: https://github.com/falkben
|
url: https://github.com/falkben
|
||||||
- login: sm-Fifteen
|
- login: sm-Fifteen
|
||||||
count: 48
|
count: 49
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4
|
||||||
url: https://github.com/sm-Fifteen
|
url: https://github.com/sm-Fifteen
|
||||||
- login: insomnes
|
- login: insomnes
|
||||||
count: 46
|
count: 46
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
|
||||||
url: https://github.com/insomnes
|
url: https://github.com/insomnes
|
||||||
|
- login: jgould22
|
||||||
|
count: 45
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
|
||||||
|
url: https://github.com/jgould22
|
||||||
- login: Dustyposa
|
- login: Dustyposa
|
||||||
count: 43
|
count: 43
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4
|
||||||
url: https://github.com/Dustyposa
|
url: https://github.com/Dustyposa
|
||||||
|
- login: adriangb
|
||||||
|
count: 40
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=75087f0cf0e9f725f3cd18a899218b6c63ae60d3&v=4
|
||||||
|
url: https://github.com/adriangb
|
||||||
- login: includeamin
|
- login: includeamin
|
||||||
count: 39
|
count: 39
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4
|
||||||
url: https://github.com/includeamin
|
url: https://github.com/includeamin
|
||||||
- login: jgould22
|
|
||||||
count: 38
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
|
|
||||||
url: https://github.com/jgould22
|
|
||||||
- login: STeveShary
|
- login: STeveShary
|
||||||
count: 37
|
count: 37
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4
|
||||||
url: https://github.com/STeveShary
|
url: https://github.com/STeveShary
|
||||||
- login: adriangb
|
- login: chbndrhnns
|
||||||
count: 36
|
count: 35
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=81f0262df34e1460ca546fbd0c211169c2478532&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
|
||||||
url: https://github.com/adriangb
|
url: https://github.com/chbndrhnns
|
||||||
- login: prostomarkeloff
|
- login: prostomarkeloff
|
||||||
count: 33
|
count: 33
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4
|
||||||
|
|
@ -85,14 +97,14 @@ experts:
|
||||||
count: 29
|
count: 29
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
|
||||||
url: https://github.com/wshayes
|
url: https://github.com/wshayes
|
||||||
- login: chbndrhnns
|
|
||||||
count: 28
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
|
|
||||||
url: https://github.com/chbndrhnns
|
|
||||||
- login: panla
|
- login: panla
|
||||||
count: 26
|
count: 29
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4
|
||||||
url: https://github.com/panla
|
url: https://github.com/panla
|
||||||
|
- login: acidjunk
|
||||||
|
count: 27
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
|
||||||
|
url: https://github.com/acidjunk
|
||||||
- login: ghandic
|
- login: ghandic
|
||||||
count: 25
|
count: 25
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4
|
||||||
|
|
@ -117,18 +129,22 @@ experts:
|
||||||
count: 21
|
count: 21
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4
|
||||||
url: https://github.com/chris-allnutt
|
url: https://github.com/chris-allnutt
|
||||||
|
- login: odiseo0
|
||||||
|
count: 21
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4
|
||||||
|
url: https://github.com/odiseo0
|
||||||
- login: retnikt
|
- login: retnikt
|
||||||
count: 19
|
count: 19
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4
|
||||||
url: https://github.com/retnikt
|
url: https://github.com/retnikt
|
||||||
- login: acidjunk
|
|
||||||
count: 18
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
|
|
||||||
url: https://github.com/acidjunk
|
|
||||||
- login: Hultner
|
- login: Hultner
|
||||||
count: 18
|
count: 18
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4
|
||||||
url: https://github.com/Hultner
|
url: https://github.com/Hultner
|
||||||
|
- login: rafsaf
|
||||||
|
count: 18
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4
|
||||||
|
url: https://github.com/rafsaf
|
||||||
- login: jorgerpo
|
- login: jorgerpo
|
||||||
count: 17
|
count: 17
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4
|
||||||
|
|
@ -141,10 +157,6 @@ experts:
|
||||||
count: 17
|
count: 17
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/1765494?u=5b1ab7c582db4b4016fa31affe977d10af108ad4&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/1765494?u=5b1ab7c582db4b4016fa31affe977d10af108ad4&v=4
|
||||||
url: https://github.com/harunyasar
|
url: https://github.com/harunyasar
|
||||||
- login: rafsaf
|
|
||||||
count: 17
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=be9f06b8ced2d2b677297decc781fa8ce4f7ddbd&v=4
|
|
||||||
url: https://github.com/rafsaf
|
|
||||||
- login: waynerv
|
- login: waynerv
|
||||||
count: 16
|
count: 16
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
|
||||||
|
|
@ -153,71 +165,63 @@ experts:
|
||||||
count: 16
|
count: 16
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4
|
||||||
url: https://github.com/dstlny
|
url: https://github.com/dstlny
|
||||||
|
- login: jonatasoli
|
||||||
|
count: 15
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4
|
||||||
|
url: https://github.com/jonatasoli
|
||||||
|
- login: hellocoldworld
|
||||||
|
count: 14
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/47581948?u=3d2186796434c507a6cb6de35189ab0ad27c356f&v=4
|
||||||
|
url: https://github.com/hellocoldworld
|
||||||
- login: haizaar
|
- login: haizaar
|
||||||
count: 13
|
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
|
url: https://github.com/haizaar
|
||||||
|
- login: yinziyan1206
|
||||||
|
count: 13
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4
|
||||||
|
url: https://github.com/yinziyan1206
|
||||||
- login: valentin994
|
- login: valentin994
|
||||||
count: 13
|
count: 13
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/42819267?u=fdeeaa9242a59b243f8603496b00994f6951d5a2&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/42819267?u=fdeeaa9242a59b243f8603496b00994f6951d5a2&v=4
|
||||||
url: https://github.com/valentin994
|
url: https://github.com/valentin994
|
||||||
- login: hellocoldworld
|
|
||||||
count: 12
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/47581948?v=4
|
|
||||||
url: https://github.com/hellocoldworld
|
|
||||||
- login: David-Lor
|
- login: David-Lor
|
||||||
count: 12
|
count: 12
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/17401854?u=474680c02b94cba810cb9032fb7eb787d9cc9d22&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/17401854?u=474680c02b94cba810cb9032fb7eb787d9cc9d22&v=4
|
||||||
url: https://github.com/David-Lor
|
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: jonatasoli
|
|
||||||
count: 12
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4
|
|
||||||
url: https://github.com/jonatasoli
|
|
||||||
- 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: juntatalor
|
|
||||||
count: 11
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/8134632?v=4
|
|
||||||
url: https://github.com/juntatalor
|
|
||||||
- login: n8sty
|
- login: n8sty
|
||||||
count: 11
|
count: 12
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4
|
||||||
url: https://github.com/n8sty
|
url: https://github.com/n8sty
|
||||||
- login: aalifadv
|
- login: zoliknemet
|
||||||
count: 11
|
count: 12
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/78442260?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4
|
||||||
url: https://github.com/aalifadv
|
url: https://github.com/zoliknemet
|
||||||
last_month_active:
|
last_month_active:
|
||||||
- login: jgould22
|
- login: JarroVGIT
|
||||||
count: 15
|
count: 27
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
|
||||||
url: https://github.com/jgould22
|
url: https://github.com/JarroVGIT
|
||||||
- login: accelleon
|
- login: iudeen
|
||||||
count: 5
|
count: 16
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/5001614?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
|
||||||
url: https://github.com/accelleon
|
url: https://github.com/iudeen
|
||||||
- login: jonatasoli
|
- login: mbroton
|
||||||
count: 4
|
count: 6
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4
|
||||||
url: https://github.com/jonatasoli
|
url: https://github.com/mbroton
|
||||||
|
- login: csrgxtu
|
||||||
|
count: 6
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/5053620?u=9655a3e9661492fcdaaf99193eb16d5cbcc3849e&v=4
|
||||||
|
url: https://github.com/csrgxtu
|
||||||
- login: Kludex
|
- login: Kludex
|
||||||
count: 4
|
count: 4
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||||
url: https://github.com/Kludex
|
url: https://github.com/Kludex
|
||||||
- login: yinziyan1206
|
- login: jgould22
|
||||||
count: 3
|
count: 3
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
|
||||||
url: https://github.com/yinziyan1206
|
url: https://github.com/jgould22
|
||||||
top_contributors:
|
top_contributors:
|
||||||
- login: waynerv
|
- login: waynerv
|
||||||
count: 25
|
count: 25
|
||||||
|
|
@ -232,9 +236,13 @@ top_contributors:
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
|
||||||
url: https://github.com/dmontagu
|
url: https://github.com/dmontagu
|
||||||
- login: jaystone776
|
- login: jaystone776
|
||||||
count: 15
|
count: 16
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4
|
||||||
url: https://github.com/jaystone776
|
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: euri10
|
- login: euri10
|
||||||
count: 13
|
count: 13
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
|
||||||
|
|
@ -244,20 +252,20 @@ top_contributors:
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4
|
||||||
url: https://github.com/mariacamilagl
|
url: https://github.com/mariacamilagl
|
||||||
- login: Smlep
|
- login: Smlep
|
||||||
count: 9
|
count: 10
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
|
||||||
url: https://github.com/Smlep
|
url: https://github.com/Smlep
|
||||||
|
- login: dependabot
|
||||||
|
count: 9
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4
|
||||||
|
url: https://github.com/apps/dependabot
|
||||||
- login: Serrones
|
- login: Serrones
|
||||||
count: 8
|
count: 8
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
|
||||||
url: https://github.com/Serrones
|
url: https://github.com/Serrones
|
||||||
- login: Kludex
|
|
||||||
count: 8
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
|
||||||
url: https://github.com/Kludex
|
|
||||||
- login: RunningIkkyu
|
- login: RunningIkkyu
|
||||||
count: 7
|
count: 7
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=706e1ee3f248245f2d68b976d149d06fd5a2010d&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=efb5b45b55584450507834f279ce48d4d64dea2f&v=4
|
||||||
url: https://github.com/RunningIkkyu
|
url: https://github.com/RunningIkkyu
|
||||||
- login: hard-coders
|
- login: hard-coders
|
||||||
count: 7
|
count: 7
|
||||||
|
|
@ -275,6 +283,10 @@ top_contributors:
|
||||||
count: 5
|
count: 5
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4
|
||||||
url: https://github.com/Attsun1031
|
url: https://github.com/Attsun1031
|
||||||
|
- login: ComicShrimp
|
||||||
|
count: 5
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=b3e4d9a14d9a65d429ce62c566aef73178b7111d&v=4
|
||||||
|
url: https://github.com/ComicShrimp
|
||||||
- login: jekirl
|
- login: jekirl
|
||||||
count: 4
|
count: 4
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/2546697?u=a027452387d85bd4a14834e19d716c99255fb3b7&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/2546697?u=a027452387d85bd4a14834e19d716c99255fb3b7&v=4
|
||||||
|
|
@ -285,21 +297,45 @@ top_contributors:
|
||||||
url: https://github.com/jfunez
|
url: https://github.com/jfunez
|
||||||
- login: ycd
|
- login: ycd
|
||||||
count: 4
|
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
|
url: https://github.com/ycd
|
||||||
- login: komtaki
|
- login: komtaki
|
||||||
count: 4
|
count: 4
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4
|
||||||
url: https://github.com/komtaki
|
url: https://github.com/komtaki
|
||||||
|
- login: hitrust
|
||||||
|
count: 4
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/3360631?u=5fa1f475ad784d64eb9666bdd43cc4d285dcc773&v=4
|
||||||
|
url: https://github.com/hitrust
|
||||||
|
- login: rjNemo
|
||||||
|
count: 4
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
|
||||||
|
url: https://github.com/rjNemo
|
||||||
|
- login: lsglucas
|
||||||
|
count: 4
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
|
||||||
|
url: https://github.com/lsglucas
|
||||||
- login: NinaHwang
|
- login: NinaHwang
|
||||||
count: 4
|
count: 4
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
|
||||||
url: https://github.com/NinaHwang
|
url: https://github.com/NinaHwang
|
||||||
|
- login: pre-commit-ci
|
||||||
|
count: 4
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4
|
||||||
|
url: https://github.com/apps/pre-commit-ci
|
||||||
top_reviewers:
|
top_reviewers:
|
||||||
- login: Kludex
|
- login: Kludex
|
||||||
count: 93
|
count: 101
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||||
url: https://github.com/Kludex
|
url: https://github.com/Kludex
|
||||||
|
- login: BilalAlpaslan
|
||||||
|
count: 64
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4
|
||||||
|
url: https://github.com/BilalAlpaslan
|
||||||
|
- login: tokusumi
|
||||||
|
count: 50
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
|
||||||
|
url: https://github.com/tokusumi
|
||||||
- login: waynerv
|
- login: waynerv
|
||||||
count: 47
|
count: 47
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
|
||||||
|
|
@ -308,34 +344,38 @@ top_reviewers:
|
||||||
count: 47
|
count: 47
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/59285379?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/59285379?v=4
|
||||||
url: https://github.com/Laineyzhang55
|
url: https://github.com/Laineyzhang55
|
||||||
- login: tokusumi
|
- login: yezz123
|
||||||
count: 46
|
count: 46
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
|
||||||
url: https://github.com/tokusumi
|
url: https://github.com/yezz123
|
||||||
- login: ycd
|
- login: ycd
|
||||||
count: 45
|
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
|
url: https://github.com/ycd
|
||||||
- login: cikay
|
- login: cikay
|
||||||
count: 41
|
count: 41
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/24587499?u=e772190a051ab0eaa9c8542fcff1892471638f2b&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/24587499?u=e772190a051ab0eaa9c8542fcff1892471638f2b&v=4
|
||||||
url: https://github.com/cikay
|
url: https://github.com/cikay
|
||||||
- login: BilalAlpaslan
|
|
||||||
count: 40
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4
|
|
||||||
url: https://github.com/BilalAlpaslan
|
|
||||||
- login: AdrianDeAnda
|
- login: AdrianDeAnda
|
||||||
count: 33
|
count: 33
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=bb7f8a0d6c9de4e9d0320a9f271210206e202250&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=b2ea249c6b41ddf98679c8d110d0f67d4a3ebf93&v=4
|
||||||
url: https://github.com/AdrianDeAnda
|
url: https://github.com/AdrianDeAnda
|
||||||
- login: ArcLightSlavik
|
- login: ArcLightSlavik
|
||||||
count: 31
|
count: 31
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
|
||||||
url: https://github.com/ArcLightSlavik
|
url: https://github.com/ArcLightSlavik
|
||||||
|
- login: JarroVGIT
|
||||||
|
count: 31
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
|
||||||
|
url: https://github.com/JarroVGIT
|
||||||
- login: cassiobotaro
|
- login: cassiobotaro
|
||||||
count: 25
|
count: 25
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4
|
||||||
url: https://github.com/cassiobotaro
|
url: https://github.com/cassiobotaro
|
||||||
|
- login: lsglucas
|
||||||
|
count: 24
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
|
||||||
|
url: https://github.com/lsglucas
|
||||||
- login: dmontagu
|
- login: dmontagu
|
||||||
count: 23
|
count: 23
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
|
||||||
|
|
@ -344,12 +384,8 @@ top_reviewers:
|
||||||
count: 21
|
count: 21
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4
|
||||||
url: https://github.com/komtaki
|
url: https://github.com/komtaki
|
||||||
- login: yezz123
|
|
||||||
count: 19
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
|
|
||||||
url: https://github.com/yezz123
|
|
||||||
- login: hard-coders
|
- login: hard-coders
|
||||||
count: 19
|
count: 20
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
|
||||||
url: https://github.com/hard-coders
|
url: https://github.com/hard-coders
|
||||||
- login: 0417taehyun
|
- login: 0417taehyun
|
||||||
|
|
@ -364,14 +400,14 @@ top_reviewers:
|
||||||
count: 16
|
count: 16
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/21978760?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/21978760?v=4
|
||||||
url: https://github.com/yanever
|
url: https://github.com/yanever
|
||||||
- login: lsglucas
|
|
||||||
count: 16
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
|
|
||||||
url: https://github.com/lsglucas
|
|
||||||
- login: SwftAlpc
|
- login: SwftAlpc
|
||||||
count: 16
|
count: 16
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4
|
||||||
url: https://github.com/SwftAlpc
|
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
|
- login: Smlep
|
||||||
count: 16
|
count: 16
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
|
||||||
|
|
@ -388,18 +424,30 @@ top_reviewers:
|
||||||
count: 15
|
count: 15
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/63476957?u=6c86e59b48e0394d4db230f37fc9ad4d7e2c27c7&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/63476957?u=6c86e59b48e0394d4db230f37fc9ad4d7e2c27c7&v=4
|
||||||
url: https://github.com/delhi09
|
url: https://github.com/delhi09
|
||||||
- login: rjNemo
|
- login: iudeen
|
||||||
count: 14
|
count: 14
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
|
||||||
url: https://github.com/rjNemo
|
url: https://github.com/iudeen
|
||||||
- login: RunningIkkyu
|
|
||||||
count: 12
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=706e1ee3f248245f2d68b976d149d06fd5a2010d&v=4
|
|
||||||
url: https://github.com/RunningIkkyu
|
|
||||||
- login: sh0nk
|
- login: sh0nk
|
||||||
count: 12
|
count: 13
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/6478810?u=af15d724875cec682ed8088a86d36b2798f981c0&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/6478810?u=af15d724875cec682ed8088a86d36b2798f981c0&v=4
|
||||||
url: https://github.com/sh0nk
|
url: https://github.com/sh0nk
|
||||||
|
- login: RunningIkkyu
|
||||||
|
count: 12
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=efb5b45b55584450507834f279ce48d4d64dea2f&v=4
|
||||||
|
url: https://github.com/RunningIkkyu
|
||||||
|
- login: odiseo0
|
||||||
|
count: 12
|
||||||
|
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4
|
||||||
|
url: https://github.com/odiseo0
|
||||||
|
- 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
|
||||||
|
url: https://github.com/solomein-sv
|
||||||
- login: mariacamilagl
|
- login: mariacamilagl
|
||||||
count: 10
|
count: 10
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4
|
||||||
|
|
@ -412,13 +460,13 @@ top_reviewers:
|
||||||
count: 10
|
count: 10
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/7887703?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/7887703?v=4
|
||||||
url: https://github.com/maoyibo
|
url: https://github.com/maoyibo
|
||||||
- login: solomein-sv
|
- login: ComicShrimp
|
||||||
count: 10
|
count: 10
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/46193920?u=46acfb4aeefb1d7b9fdc5a8cbd9eb8744683c47a&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=b3e4d9a14d9a65d429ce62c566aef73178b7111d&v=4
|
||||||
url: https://github.com/solomein-sv
|
url: https://github.com/ComicShrimp
|
||||||
- login: graingert
|
- login: graingert
|
||||||
count: 9
|
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
|
url: https://github.com/graingert
|
||||||
- login: PandaHun
|
- login: PandaHun
|
||||||
count: 9
|
count: 9
|
||||||
|
|
@ -432,6 +480,14 @@ top_reviewers:
|
||||||
count: 9
|
count: 9
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4
|
||||||
url: https://github.com/bezaca
|
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
|
||||||
|
url: https://github.com/raphaelauv
|
||||||
- login: blt232018
|
- login: blt232018
|
||||||
count: 8
|
count: 8
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/43393471?u=172b0e0391db1aa6c1706498d6dfcb003c8a4857&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/43393471?u=172b0e0391db1aa6c1706498d6dfcb003c8a4857&v=4
|
||||||
|
|
@ -440,10 +496,6 @@ top_reviewers:
|
||||||
count: 8
|
count: 8
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/5690226?v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/5690226?v=4
|
||||||
url: https://github.com/rogerbrinkmann
|
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
|
- login: NinaHwang
|
||||||
count: 8
|
count: 8
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
|
||||||
|
|
@ -456,39 +508,15 @@ top_reviewers:
|
||||||
count: 7
|
count: 7
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
|
||||||
url: https://github.com/Serrones
|
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
|
- login: ryuckel
|
||||||
count: 7
|
count: 7
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/36391432?u=094eec0cfddd5013f76f31e55e56147d78b19553&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/36391432?u=094eec0cfddd5013f76f31e55e56147d78b19553&v=4
|
||||||
url: https://github.com/ryuckel
|
url: https://github.com/ryuckel
|
||||||
- login: raphaelauv
|
|
||||||
count: 7
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
|
|
||||||
url: https://github.com/raphaelauv
|
|
||||||
- login: NastasiaSaby
|
- login: NastasiaSaby
|
||||||
count: 7
|
count: 7
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/8245071?u=b3afd005f9e4bf080c219ef61a592b3a8004b764&v=4
|
avatarUrl: https://avatars.githubusercontent.com/u/8245071?u=b3afd005f9e4bf080c219ef61a592b3a8004b764&v=4
|
||||||
url: https://github.com/NastasiaSaby
|
url: https://github.com/NastasiaSaby
|
||||||
- login: Mause
|
|
||||||
count: 7
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
|
|
||||||
url: https://github.com/Mause
|
|
||||||
- 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
|
|
||||||
- login: jovicon
|
|
||||||
count: 6
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/21287303?u=b049eac3e51a4c0473c2efe66b4d28a7d8f2b572&v=4
|
|
||||||
url: https://github.com/jovicon
|
|
||||||
- login: LorhanSohaky
|
|
||||||
count: 6
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4
|
|
||||||
url: https://github.com/LorhanSohaky
|
|
||||||
- login: peidrao
|
|
||||||
count: 6
|
|
||||||
avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=88c2cb42a99e0f50cdeae3606992568184783ee5&v=4
|
|
||||||
url: https://github.com/peidrao
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
gold:
|
gold:
|
||||||
- url: https://bit.ly/2QSouzH
|
- url: https://bit.ly/3dmXC5S
|
||||||
title: "Jina: build neural search-as-a-service for any kind of data in just minutes."
|
title: The data structure for unstructured multimodal data
|
||||||
img: https://fastapi.tiangolo.com/img/sponsors/jina.svg
|
img: https://fastapi.tiangolo.com/img/sponsors/docarray.svg
|
||||||
|
- url: https://bit.ly/3JJ7y5C
|
||||||
|
title: Build cross-modal and multimodal applications on the cloud
|
||||||
|
img: https://fastapi.tiangolo.com/img/sponsors/jina2.svg
|
||||||
- url: https://cryptapi.io/
|
- url: https://cryptapi.io/
|
||||||
title: "CryptAPI: Your easy to use, secure and privacy oriented payment gateway."
|
title: "CryptAPI: Your easy to use, secure and privacy oriented payment gateway."
|
||||||
img: https://fastapi.tiangolo.com/img/sponsors/cryptapi.svg
|
img: https://fastapi.tiangolo.com/img/sponsors/cryptapi.svg
|
||||||
- url: https://classiq.link/n4s
|
- url: https://doist.com/careers/9B437B1615-wa-senior-backend-engineer-python
|
||||||
title: Join the team building a new SaaS platform that will change the computing world
|
title: Help us migrate doist to FastAPI
|
||||||
img: https://fastapi.tiangolo.com/img/sponsors/classiq.png
|
img: https://fastapi.tiangolo.com/img/sponsors/doist.svg
|
||||||
- url: https://www.dropbase.io/careers
|
|
||||||
title: Dropbase - seamlessly collect, clean, and centralize data.
|
|
||||||
img: https://fastapi.tiangolo.com/img/sponsors/dropbase.svg
|
|
||||||
silver:
|
silver:
|
||||||
- url: https://www.deta.sh/?ref=fastapi
|
- url: https://www.deta.sh/?ref=fastapi
|
||||||
title: The launchpad for all your (team's) ideas
|
title: The launchpad for all your (team's) ideas
|
||||||
|
|
@ -37,6 +37,6 @@ bronze:
|
||||||
- url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source
|
- url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source
|
||||||
title: Biosecurity risk assessments made easy.
|
title: Biosecurity risk assessments made easy.
|
||||||
img: https://fastapi.tiangolo.com/img/sponsors/exoflare.png
|
img: https://fastapi.tiangolo.com/img/sponsors/exoflare.png
|
||||||
- url: https://striveworks.us/careers?utm_source=fastapi&utm_medium=sponsor_banner&utm_campaign=feb_march#openings
|
- url: https://bit.ly/3ccLCmM
|
||||||
title: https://striveworks.us/careers
|
title: https://striveworks.us/careers
|
||||||
img: https://fastapi.tiangolo.com/img/sponsors/striveworks.png
|
img: https://fastapi.tiangolo.com/img/sponsors/striveworks2.png
|
||||||
|
|
|
||||||
|
|
@ -10,3 +10,6 @@ logins:
|
||||||
- InesIvanova
|
- InesIvanova
|
||||||
- DropbaseHQ
|
- DropbaseHQ
|
||||||
- VincentParedes
|
- VincentParedes
|
||||||
|
- BLUE-DEVIL1134
|
||||||
|
- ObliviousAI
|
||||||
|
- Doist
|
||||||
|
|
|
||||||
|
|
@ -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:
|
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!}
|
{!../../../docs_src/additional_responses/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ But you also want it to accept new items. And when the items didn't exist before
|
||||||
|
|
||||||
To achieve that, import `JSONResponse`, and return your content there directly, setting the `status_code` that you want:
|
To achieve that, import `JSONResponse`, and return your content there directly, setting the `status_code` that you want:
|
||||||
|
|
||||||
```Python hl_lines="4 23"
|
```Python hl_lines="4 25"
|
||||||
{!../../../docs_src/additional_status_codes/tutorial001.py!}
|
{!../../../docs_src/additional_status_codes/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,23 @@ The important difference for us is that with HTTPX we are not limited to synchro
|
||||||
|
|
||||||
## Example
|
## 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
|
```Python
|
||||||
{!../../../docs_src/async_tests/main.py!}
|
{!../../../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
|
```Python
|
||||||
{!../../../docs_src/async_tests/test_main.py!}
|
{!../../../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*.
|
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"
|
```Python hl_lines="2 7"
|
||||||
{!../../../docs_src/custom_response/tutorial001b.py!}
|
{!../../../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.
|
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
|
## Default response class
|
||||||
|
|
||||||
When creating a **FastAPI** class instance or an `APIRouter` you can specify which response class to use by default.
|
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!}
|
{!../../../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.
|
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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -132,8 +132,8 @@ You can probably right-click each link and select an option similar to `Save lin
|
||||||
|
|
||||||
**Swagger UI** uses the files:
|
**Swagger UI** uses the files:
|
||||||
|
|
||||||
* <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@3/swagger-ui-bundle.js" class="external-link" target="_blank">`swagger-ui-bundle.js`</a>
|
* <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui-bundle.js" class="external-link" target="_blank">`swagger-ui-bundle.js`</a>
|
||||||
* <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@3/swagger-ui.css" class="external-link" target="_blank">`swagger-ui.css`</a>
|
* <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui.css" class="external-link" target="_blank">`swagger-ui.css`</a>
|
||||||
|
|
||||||
And **ReDoc** uses the file:
|
And **ReDoc** uses the file:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ It will have a *path operation* that will receive an `Invoice` body, and a query
|
||||||
|
|
||||||
This part is pretty normal, most of the code is probably already familiar to you:
|
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!}
|
{!../../../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.
|
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!}
|
{!../../../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`.
|
* 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`.
|
* 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!}
|
{!../../../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:
|
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!}
|
{!../../../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.
|
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!}
|
{!../../../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
|
```Python
|
||||||
if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"):
|
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:
|
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!}
|
{!../../../docs_src/security/tutorial007.py!}
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ To override a dependency for testing, you put as a key the original dependency (
|
||||||
|
|
||||||
And then **FastAPI** will call that override instead of the original dependency.
|
And then **FastAPI** will call that override instead of the original dependency.
|
||||||
|
|
||||||
```Python hl_lines="26-27 30"
|
```Python hl_lines="28-29 32"
|
||||||
{!../../../docs_src/dependency_testing/tutorial001.py!}
|
{!../../../docs_src/dependency_testing/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,20 @@
|
||||||
|
|
||||||
You can use <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API" class="external-link" target="_blank">WebSockets</a> with **FastAPI**.
|
You can use <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API" class="external-link" target="_blank">WebSockets</a> with **FastAPI**.
|
||||||
|
|
||||||
|
## Install `WebSockets`
|
||||||
|
|
||||||
|
First you need to install `WebSockets`:
|
||||||
|
|
||||||
|
<div class="termy">
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ pip install websockets
|
||||||
|
|
||||||
|
---> 100%
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
## WebSockets client
|
## WebSockets client
|
||||||
|
|
||||||
### In production
|
### In production
|
||||||
|
|
|
||||||
|
|
@ -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.
|
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.
|
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"
|
```Python hl_lines="2"
|
||||||
@app.get('/')
|
@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.
|
Anyway, in any of the cases above, FastAPI will still work asynchronously and be extremely fast.
|
||||||
|
|
||||||
|
|
@ -102,87 +102,117 @@ To see the difference, imagine the following story about burgers:
|
||||||
|
|
||||||
### Concurrent Burgers
|
### Concurrent Burgers
|
||||||
|
|
||||||
<!-- The gender neutral cook emoji "🧑🍳" does not render well in browsers. In the meantime, I'm using a mix of male "👨🍳" and female "👩🍳" cooks. -->
|
You go with your crush to get fast food, you stand in line while the cashier takes the orders from the people in front of you. 😍
|
||||||
|
|
||||||
You go with your crush 😍 to get fast food 🍔, you stand in line while the cashier 💁 takes the orders from the people in front of you.
|
<img src="/img/async/concurrent-burgers/concurrent-burgers-01.png" class="illustration">
|
||||||
|
|
||||||
Then it's your turn, you place your order of 2 very fancy burgers 🍔 for your crush 😍 and you.
|
Then it's your turn, you place your order of 2 very fancy burgers for your crush and you. 🍔🍔
|
||||||
|
|
||||||
You pay 💸.
|
<img src="/img/async/concurrent-burgers/concurrent-burgers-02.png" class="illustration">
|
||||||
|
|
||||||
The cashier 💁 says something to the cook in the kitchen 👨🍳 so they know they have to prepare your burgers 🍔 (even though they are currently preparing the ones for the previous clients).
|
The cashier says something to the cook in the kitchen so they know they have to prepare your burgers (even though they are currently preparing the ones for the previous clients).
|
||||||
|
|
||||||
The cashier 💁 gives you the number of your turn.
|
<img src="/img/async/concurrent-burgers/concurrent-burgers-03.png" class="illustration">
|
||||||
|
|
||||||
While you are waiting, you go with your crush 😍 and pick a table, you sit and talk with your crush 😍 for a long time (as your burgers are very fancy and take some time to prepare ✨🍔✨).
|
You pay. 💸
|
||||||
|
|
||||||
As you are sitting at the table with your crush 😍, while you wait for the burgers 🍔, you can spend that time admiring how awesome, cute and smart your crush is ✨😍✨.
|
The cashier gives you the number of your turn.
|
||||||
|
|
||||||
While waiting and talking to your crush 😍, from time to time, you check the number displayed on the counter to see if it's your turn already.
|
<img src="/img/async/concurrent-burgers/concurrent-burgers-04.png" class="illustration">
|
||||||
|
|
||||||
Then at some point, it finally is your turn. You go to the counter, get your burgers 🍔 and come back to the table.
|
While you are waiting, you go with your crush and pick a table, you sit and talk with your crush for a long time (as your burgers are very fancy and take some time to prepare).
|
||||||
|
|
||||||
You and your crush 😍 eat the burgers 🍔 and have a nice time ✨.
|
As you are sitting at the table with your crush, while you wait for the burgers, you can spend that time admiring how awesome, cute and smart your crush is ✨😍✨.
|
||||||
|
|
||||||
|
<img src="/img/async/concurrent-burgers/concurrent-burgers-05.png" class="illustration">
|
||||||
|
|
||||||
|
While waiting and talking to your crush, from time to time, you check the number displayed on the counter to see if it's your turn already.
|
||||||
|
|
||||||
|
Then at some point, it finally is your turn. You go to the counter, get your burgers and come back to the table.
|
||||||
|
|
||||||
|
<img src="/img/async/concurrent-burgers/concurrent-burgers-06.png" class="illustration">
|
||||||
|
|
||||||
|
You and your crush eat the burgers and have a nice time. ✨
|
||||||
|
|
||||||
|
<img src="/img/async/concurrent-burgers/concurrent-burgers-07.png" class="illustration">
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
Beautiful illustrations by <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a>. 🎨
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Imagine you are the computer / program 🤖 in that story.
|
Imagine you are the computer / program 🤖 in that story.
|
||||||
|
|
||||||
While you are at the line, you are just idle 😴, waiting for your turn, not doing anything very "productive". But the line is fast because the cashier 💁 is only taking the orders (not preparing them), so that's fine.
|
While you are at the line, you are just idle 😴, waiting for your turn, not doing anything very "productive". But the line is fast because the cashier is only taking the orders (not preparing them), so that's fine.
|
||||||
|
|
||||||
Then, when it's your turn, you do actual "productive" work 🤓, you process the menu, decide what you want, get your crush's 😍 choice, pay 💸, check that you give the correct bill or card, check that you are charged correctly, check that the order has the correct items, etc.
|
Then, when it's your turn, you do actual "productive" work, you process the menu, decide what you want, get your crush's choice, pay, check that you give the correct bill or card, check that you are charged correctly, check that the order has the correct items, etc.
|
||||||
|
|
||||||
But then, even though you still don't have your burgers 🍔, your work with the cashier 💁 is "on pause" ⏸, because you have to wait 🕙 for your burgers to be ready.
|
But then, even though you still don't have your burgers, your work with the cashier is "on pause" ⏸, because you have to wait 🕙 for your burgers to be ready.
|
||||||
|
|
||||||
But as you go away from the counter and sit at the table with a number for your turn, you can switch 🔀 your attention to your crush 😍, and "work" ⏯ 🤓 on that. Then you are again doing something very "productive" 🤓, as is flirting with your crush 😍.
|
But as you go away from the counter and sit at the table with a number for your turn, you can switch 🔀 your attention to your crush, and "work" ⏯ 🤓 on that. Then you are again doing something very "productive" as is flirting with your crush 😍.
|
||||||
|
|
||||||
Then the cashier 💁 says "I'm finished with doing the burgers" 🍔 by putting your number on the counter's display, but you don't jump like crazy immediately when the displayed number changes to your turn number. You know no one will steal your burgers 🍔 because you have the number of your turn, and they have theirs.
|
Then the cashier 💁 says "I'm finished with doing the burgers" by putting your number on the counter's display, but you don't jump like crazy immediately when the displayed number changes to your turn number. You know no one will steal your burgers because you have the number of your turn, and they have theirs.
|
||||||
|
|
||||||
So you wait for your crush 😍 to finish the story (finish the current work ⏯ / task being processed 🤓), smile gently and say that you are going for the burgers ⏸.
|
So you wait for your crush to finish the story (finish the current work ⏯ / task being processed 🤓), smile gently and say that you are going for the burgers ⏸.
|
||||||
|
|
||||||
Then you go to the counter 🔀, to the initial task that is now finished ⏯, pick the burgers 🍔, say thanks and take them to the table. That finishes that step / task of interaction with the counter ⏹. That in turn, creates a new task, of "eating burgers" 🔀 ⏯, but the previous one of "getting burgers" is finished ⏹.
|
Then you go to the counter 🔀, to the initial task that is now finished ⏯, pick the burgers, say thanks and take them to the table. That finishes that step / task of interaction with the counter ⏹. That in turn, creates a new task, of "eating burgers" 🔀 ⏯, but the previous one of "getting burgers" is finished ⏹.
|
||||||
|
|
||||||
### Parallel Burgers
|
### Parallel Burgers
|
||||||
|
|
||||||
Now let's imagine these aren't "Concurrent Burgers", but "Parallel Burgers".
|
Now let's imagine these aren't "Concurrent Burgers", but "Parallel Burgers".
|
||||||
|
|
||||||
You go with your crush 😍 to get parallel fast food 🍔.
|
You go with your crush to get parallel fast food.
|
||||||
|
|
||||||
You stand in line while several (let's say 8) cashiers that at the same time are cooks 👩🍳👨🍳👩🍳👨🍳👩🍳👨🍳👩🍳👨🍳 take the orders from the people in front of you.
|
You stand in line while several (let's say 8) cashiers that at the same time are cooks take the orders from the people in front of you.
|
||||||
|
|
||||||
Everyone before you is waiting 🕙 for their burgers 🍔 to be ready before leaving the counter because each of the 8 cashiers goes and prepares the burger right away before getting the next order.
|
Everyone before you is waiting for their burgers to be ready before leaving the counter because each of the 8 cashiers goes and prepares the burger right away before getting the next order.
|
||||||
|
|
||||||
Then it's finally your turn, you place your order of 2 very fancy burgers 🍔 for your crush 😍 and you.
|
<img src="/img/async/parallel-burgers/parallel-burgers-01.png" class="illustration">
|
||||||
|
|
||||||
|
Then it's finally your turn, you place your order of 2 very fancy burgers for your crush and you.
|
||||||
|
|
||||||
You pay 💸.
|
You pay 💸.
|
||||||
|
|
||||||
The cashier goes to the kitchen 👨🍳.
|
<img src="/img/async/parallel-burgers/parallel-burgers-02.png" class="illustration">
|
||||||
|
|
||||||
You wait, standing in front of the counter 🕙, so that no one else takes your burgers 🍔 before you do, as there are no numbers for turns.
|
The cashier goes to the kitchen.
|
||||||
|
|
||||||
As you and your crush 😍 are busy not letting anyone get in front of you and take your burgers whenever they arrive 🕙, you cannot pay attention to your crush 😞.
|
You wait, standing in front of the counter 🕙, so that no one else takes your burgers before you do, as there are no numbers for turns.
|
||||||
|
|
||||||
This is "synchronous" work, you are "synchronized" with the cashier/cook 👨🍳. You have to wait 🕙 and be there at the exact moment that the cashier/cook 👨🍳 finishes the burgers 🍔 and gives them to you, or otherwise, someone else might take them.
|
<img src="/img/async/parallel-burgers/parallel-burgers-03.png" class="illustration">
|
||||||
|
|
||||||
Then your cashier/cook 👨🍳 finally comes back with your burgers 🍔, after a long time waiting 🕙 there in front of the counter.
|
As you and your crush are busy not letting anyone get in front of you and take your burgers whenever they arrive, you cannot pay attention to your crush. 😞
|
||||||
|
|
||||||
You take your burgers 🍔 and go to the table with your crush 😍.
|
This is "synchronous" work, you are "synchronized" with the cashier/cook 👨🍳. You have to wait 🕙 and be there at the exact moment that the cashier/cook 👨🍳 finishes the burgers and gives them to you, or otherwise, someone else might take them.
|
||||||
|
|
||||||
You just eat them, and you are done 🍔 ⏹.
|
<img src="/img/async/parallel-burgers/parallel-burgers-04.png" class="illustration">
|
||||||
|
|
||||||
There was not much talk or flirting as most of the time was spent waiting 🕙 in front of the counter 😞.
|
Then your cashier/cook 👨🍳 finally comes back with your burgers, after a long time waiting 🕙 there in front of the counter.
|
||||||
|
|
||||||
|
<img src="/img/async/parallel-burgers/parallel-burgers-05.png" class="illustration">
|
||||||
|
|
||||||
|
You take your burgers and go to the table with your crush.
|
||||||
|
|
||||||
|
You just eat them, and you are done. ⏹
|
||||||
|
|
||||||
|
<img src="/img/async/parallel-burgers/parallel-burgers-06.png" class="illustration">
|
||||||
|
|
||||||
|
There was not much talk or flirting as most of the time was spent waiting 🕙 in front of the counter. 😞
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
Beautiful illustrations by <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a>. 🎨
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
In this scenario of the parallel burgers, you are a computer / program 🤖 with two processors (you and your crush 😍), both waiting 🕙 and dedicating their attention ⏯ to be "waiting on the counter" 🕙 for a long time.
|
In this scenario of the parallel burgers, you are a computer / program 🤖 with two processors (you and your crush), both waiting 🕙 and dedicating their attention ⏯ to be "waiting on the counter" 🕙 for a long time.
|
||||||
|
|
||||||
The fast food store has 8 processors (cashiers/cooks) 👩🍳👨🍳👩🍳👨🍳👩🍳👨🍳👩🍳👨🍳. While the concurrent burgers store might have had only 2 (one cashier and one cook) 💁 👨🍳.
|
The fast food store has 8 processors (cashiers/cooks). While the concurrent burgers store might have had only 2 (one cashier and one cook).
|
||||||
|
|
||||||
But still, the final experience is not the best 😞.
|
But still, the final experience is not the best. 😞
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
This would be the parallel equivalent story for burgers 🍔.
|
This would be the parallel equivalent story for burgers. 🍔
|
||||||
|
|
||||||
For a more "real life" example of this, imagine a bank.
|
For a more "real life" example of this, imagine a bank.
|
||||||
|
|
||||||
|
|
@ -208,11 +238,7 @@ This "waiting" 🕙 is measured in microseconds, but still, summing it all, it's
|
||||||
|
|
||||||
That's why it makes a lot of sense to use asynchronous ⏸🔀⏯ code for web APIs.
|
That's why it makes a lot of sense to use asynchronous ⏸🔀⏯ code for web APIs.
|
||||||
|
|
||||||
Most of the existing popular Python frameworks (including Flask and Django) were created before the new asynchronous features in Python existed. So, the ways they can be deployed support parallel execution and an older form of asynchronous execution that is not as powerful as the new capabilities.
|
This kind of asynchronicity is what made NodeJS popular (even though NodeJS is not parallel) and that's the strength of Go as a programming language.
|
||||||
|
|
||||||
Even though the main specification for asynchronous web Python (ASGI) was developed at Django, to add support for WebSockets.
|
|
||||||
|
|
||||||
That kind of asynchronicity is what made NodeJS popular (even though NodeJS is not parallel) and that's the strength of Go as a programming language.
|
|
||||||
|
|
||||||
And that's the same level of performance you get with **FastAPI**.
|
And that's the same level of performance you get with **FastAPI**.
|
||||||
|
|
||||||
|
|
@ -238,7 +264,7 @@ You could have turns as in the burgers example, first the living room, then the
|
||||||
|
|
||||||
It would take the same amount of time to finish with or without turns (concurrency) and you would have done the same amount of work.
|
It would take the same amount of time to finish with or without turns (concurrency) and you would have done the same amount of work.
|
||||||
|
|
||||||
But in this case, if you could bring the 8 ex-cashier/cooks/now-cleaners 👩🍳👨🍳👩🍳👨🍳👩🍳👨🍳👩🍳👨🍳, and each one of them (plus you) could take a zone of the house to clean it, you could do all the work in **parallel**, with the extra help, and finish much sooner.
|
But in this case, if you could bring the 8 ex-cashier/cooks/now-cleaners, and each one of them (plus you) could take a zone of the house to clean it, you could do all the work in **parallel**, with the extra help, and finish much sooner.
|
||||||
|
|
||||||
In this scenario, each one of the cleaners (including you) would be a processor, doing their part of the job.
|
In this scenario, each one of the cleaners (including you) would be a processor, doing their part of the job.
|
||||||
|
|
||||||
|
|
@ -371,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.
|
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
|
### 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).
|
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.
|
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
|
### 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
|
### 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
|
### 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. 🎉
|
If it shows the `pip` binary at `env/bin/pip` then it worked. 🎉
|
||||||
|
|
||||||
|
Make sure you have the latest pip version on your virtual environment to avoid errors on the next steps:
|
||||||
|
|
||||||
!!! 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`:
|
|
||||||
|
|
||||||
<div class="termy">
|
<div class="termy">
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ pip install flit
|
$ python -m pip install --upgrade pip
|
||||||
|
|
||||||
---> 100%
|
---> 100%
|
||||||
```
|
```
|
||||||
|
|
||||||
</div>
|
</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
|
<div class="termy">
|
||||||
$ flit install --deps develop --symlink
|
|
||||||
|
|
||||||
---> 100%
|
```console
|
||||||
```
|
$ pip install -e ."[dev,doc,test]"
|
||||||
|
|
||||||
</div>
|
---> 100%
|
||||||
|
```
|
||||||
|
|
||||||
=== "Windows"
|
</div>
|
||||||
|
|
||||||
If you are on Windows, use `--pth-file` instead of `--symlink`:
|
|
||||||
|
|
||||||
<div class="termy">
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ flit install --deps develop --pth-file
|
|
||||||
|
|
||||||
---> 100%
|
|
||||||
```
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
It will install all the dependencies and your local FastAPI in your local environment.
|
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.
|
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.
|
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.
|
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
|
## Docs
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,21 @@
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.termy {
|
||||||
|
/* For right to left languages */
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
|
||||||
.termy [data-termynal] {
|
.termy [data-termynal] {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.external-link {
|
||||||
|
/* For right to left languages */
|
||||||
|
direction: ltr;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
a.external-link::after {
|
a.external-link::after {
|
||||||
/* \00A0 is a non-breaking space
|
/* \00A0 is a non-breaking space
|
||||||
to make the mark be on the same line as the link
|
to make the mark be on the same line as the link
|
||||||
|
|
@ -94,7 +105,7 @@ a.announce-link:hover {
|
||||||
.announce-wrapper .sponsor-badge {
|
.announce-wrapper .sponsor-badge {
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -5px;
|
top: -10px;
|
||||||
right: 0;
|
right: 0;
|
||||||
font-size: 0.5rem;
|
font-size: 0.5rem;
|
||||||
color: #999;
|
color: #999;
|
||||||
|
|
@ -118,3 +129,18 @@ a.announce-link:hover {
|
||||||
.twitter {
|
.twitter {
|
||||||
color: #00acee;
|
color: #00acee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Right to left languages */
|
||||||
|
code {
|
||||||
|
direction: ltr;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-content__inner h1 {
|
||||||
|
direction: ltr !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.illustration {
|
||||||
|
margin-top: 2em;
|
||||||
|
margin-bottom: 2em;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ Successfully installed fastapi pydantic uvicorn
|
||||||
* Create a `main.py` file with:
|
* Create a `main.py` file with:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
from typing import Optional
|
from typing import Union
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
|
@ -155,7 +155,7 @@ def read_root():
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
def read_item(item_id: int, q: Optional[str] = None):
|
def read_item(item_id: int, q: Union[str, None] = None):
|
||||||
return {"item_id": item_id, "q": q}
|
return {"item_id": item_id, "q": q}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -190,11 +190,11 @@ With **FastAPI** you get all of **Pydantic**'s features (as FastAPI is based on
|
||||||
* Plays nicely with your **<abbr title="Integrated Development Environment, similar to a code editor">IDE</abbr>/<abbr title="A program that checks for code errors">linter</abbr>/brain**:
|
* Plays nicely with your **<abbr title="Integrated Development Environment, similar to a code editor">IDE</abbr>/<abbr title="A program that checks for code errors">linter</abbr>/brain**:
|
||||||
* Because pydantic data structures are just instances of classes you define; auto-completion, linting, mypy and your intuition should all work properly with your validated data.
|
* Because pydantic data structures are just instances of classes you define; auto-completion, linting, mypy and your intuition should all work properly with your validated data.
|
||||||
* **Fast**:
|
* **Fast**:
|
||||||
* in <a href="https://pydantic-docs.helpmanual.io/#benchmarks-tag" class="external-link" target="_blank">benchmarks</a> Pydantic is faster than all other tested libraries.
|
* in <a href="https://pydantic-docs.helpmanual.io/benchmarks/" class="external-link" target="_blank">benchmarks</a> Pydantic is faster than all other tested libraries.
|
||||||
* Validate **complex structures**:
|
* Validate **complex structures**:
|
||||||
* Use of hierarchical Pydantic models, Python `typing`’s `List` and `Dict`, etc.
|
* 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.
|
* 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.
|
* 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.
|
* 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.
|
* 100% test coverage.
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 199 KiB |
|
After Width: | Height: | Size: 163 KiB |
|
After Width: | Height: | Size: 169 KiB |
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 156 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 166 KiB |
BIN
docs/en/docs/img/async/parallel-burgers/parallel-burgers-01.png
Normal file
|
After Width: | Height: | Size: 221 KiB |
BIN
docs/en/docs/img/async/parallel-burgers/parallel-burgers-02.png
Normal file
|
After Width: | Height: | Size: 199 KiB |
BIN
docs/en/docs/img/async/parallel-burgers/parallel-burgers-03.png
Normal file
|
After Width: | Height: | Size: 165 KiB |
BIN
docs/en/docs/img/async/parallel-burgers/parallel-burgers-04.png
Normal file
|
After Width: | Height: | Size: 214 KiB |
BIN
docs/en/docs/img/async/parallel-burgers/parallel-burgers-05.png
Normal file
|
After Width: | Height: | Size: 181 KiB |
BIN
docs/en/docs/img/async/parallel-burgers/parallel-burgers-06.png
Normal file
|
After Width: | Height: | Size: 153 KiB |
1
docs/en/docs/img/sponsors/docarray-top-banner.svg
Normal file
|
After Width: | Height: | Size: 107 KiB |
1
docs/en/docs/img/sponsors/docarray.svg
Normal file
|
After Width: | Height: | Size: 127 KiB |
46
docs/en/docs/img/sponsors/doist-banner.svg
Normal file
|
After Width: | Height: | Size: 52 KiB |
54
docs/en/docs/img/sponsors/doist.svg
Normal file
|
After Width: | Height: | Size: 91 KiB |
14
docs/en/docs/img/sponsors/imgwhale-banner.svg
Normal file
|
After Width: | Height: | Size: 105 KiB |
28
docs/en/docs/img/sponsors/imgwhale.svg
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
docs/en/docs/img/sponsors/jina-ai-banner.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/en/docs/img/sponsors/jina-ai.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
1
docs/en/docs/img/sponsors/jina-top-banner.svg
Normal file
|
After Width: | Height: | Size: 159 KiB |
1
docs/en/docs/img/sponsors/jina2.svg
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
docs/en/docs/img/sponsors/striveworks2.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
|
|
@ -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:
|
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**: 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%. *
|
* **Fast to code**: Increase the speed to develop features by about 200% to 300%. *
|
||||||
* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. *
|
* **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.
|
* **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
|
## Requirements
|
||||||
|
|
||||||
Python 3.6+
|
Python 3.7+
|
||||||
|
|
||||||
FastAPI stands on the shoulders of giants:
|
FastAPI stands on the shoulders of giants:
|
||||||
|
|
||||||
|
|
@ -129,7 +128,7 @@ $ pip install fastapi
|
||||||
|
|
||||||
</div>
|
</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">
|
<div class="termy">
|
||||||
|
|
||||||
|
|
@ -148,7 +147,7 @@ $ pip install "uvicorn[standard]"
|
||||||
* Create a file `main.py` with:
|
* Create a file `main.py` with:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
from typing import Optional
|
from typing import Union
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
|
@ -161,7 +160,7 @@ def read_root():
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
def read_item(item_id: int, q: Optional[str] = None):
|
def read_item(item_id: int, q: Union[str, None] = None):
|
||||||
return {"item_id": item_id, "q": q}
|
return {"item_id": item_id, "q": q}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -171,7 +170,7 @@ def read_item(item_id: int, q: Optional[str] = None):
|
||||||
If your code uses `async` / `await`, use `async def`:
|
If your code uses `async` / `await`, use `async def`:
|
||||||
|
|
||||||
```Python hl_lines="9 14"
|
```Python hl_lines="9 14"
|
||||||
from typing import Optional
|
from typing import Union
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
|
@ -184,7 +183,7 @@ async def read_root():
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
async def read_item(item_id: int, q: Optional[str] = None):
|
async def read_item(item_id: int, q: Union[str, None] = None):
|
||||||
return {"item_id": item_id, "q": q}
|
return {"item_id": item_id, "q": q}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -263,7 +262,7 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
|
||||||
Declare the body using standard Python types, thanks to Pydantic.
|
Declare the body using standard Python types, thanks to Pydantic.
|
||||||
|
|
||||||
```Python hl_lines="4 9-12 25-27"
|
```Python hl_lines="4 9-12 25-27"
|
||||||
from typing import Optional
|
from typing import Union
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
@ -274,7 +273,7 @@ app = FastAPI()
|
||||||
class Item(BaseModel):
|
class Item(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
price: float
|
price: float
|
||||||
is_offer: Optional[bool] = None
|
is_offer: Union[bool, None] = None
|
||||||
|
|
||||||
|
|
||||||
@app.get("/")
|
@app.get("/")
|
||||||
|
|
@ -283,7 +282,7 @@ def read_root():
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
def read_item(item_id: int, q: Optional[str] = None):
|
def read_item(item_id: int, q: Union[str, None] = None):
|
||||||
return {"item_id": item_id, "q": q}
|
return {"item_id": item_id, "q": q}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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.
|
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`:
|
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.
|
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
|
#### List
|
||||||
|
|
||||||
|
|
@ -267,7 +267,7 @@ You can declare that a variable can be any of **several types**, for example, an
|
||||||
|
|
||||||
In Python 3.6 and above (including Python 3.10) you can use the `Union` type from `typing` and put inside the square brackets the possible types to accept.
|
In Python 3.6 and above (including Python 3.10) you can use the `Union` type from `typing` and put inside the square brackets the possible types to accept.
|
||||||
|
|
||||||
In Python 3.10 there's also an **alternative syntax** were you can put the possible types separated by a <abbr title='also called "bitwise or operator", but that meaning is not relevant here'>vertical bar (`|`)</abbr>.
|
In Python 3.10 there's also an **alternative syntax** where you can put the possible types separated by a <abbr title='also called "bitwise or operator", but that meaning is not relevant here'>vertical bar (`|`)</abbr>.
|
||||||
|
|
||||||
=== "Python 3.6 and above"
|
=== "Python 3.6 and above"
|
||||||
|
|
||||||
|
|
@ -317,6 +317,45 @@ This also means that in Python 3.10, you can use `Something | None`:
|
||||||
{!> ../../../docs_src/python_types/tutorial009_py310.py!}
|
{!> ../../../docs_src/python_types/tutorial009_py310.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Using `Union` or `Optional`
|
||||||
|
|
||||||
|
If you are using a Python version below 3.10, here's a tip from my very **subjective** point of view:
|
||||||
|
|
||||||
|
* 🚨 Avoid using `Optional[SomeType]`
|
||||||
|
* Instead ✨ **use `Union[SomeType, None]`** ✨.
|
||||||
|
|
||||||
|
Both are equivalent and underneath they are the same, but I would recommend `Union` instead of `Optional` because the word "**optional**" would seem to imply that the value is optional, and it actually means "it can be `None`", even if it's not optional and is still required.
|
||||||
|
|
||||||
|
I think `Union[SomeType, None]` is more explicit about what it means.
|
||||||
|
|
||||||
|
It's just about the words and names. But those words can affect how you and your teammates think about the code.
|
||||||
|
|
||||||
|
As an example, let's take this function:
|
||||||
|
|
||||||
|
```Python hl_lines="1 4"
|
||||||
|
{!../../../docs_src/python_types/tutorial009c.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
The parameter `name` is defined as `Optional[str]`, but it is **not optional**, you cannot call the function without the parameter:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
say_hi() # Oh, no, this throws an error! 😱
|
||||||
|
```
|
||||||
|
|
||||||
|
The `name` parameter is **still required** (not *optional*) because it doesn't have a default value. Still, `name` accepts `None` as the value:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
say_hi(name=None) # This works, None is valid 🎉
|
||||||
|
```
|
||||||
|
|
||||||
|
The good news is, once you are on Python 3.10 you won't have to worry about that, as you will be able to simply use `|` to define unions of types:
|
||||||
|
|
||||||
|
```Python hl_lines="1 4"
|
||||||
|
{!../../../docs_src/python_types/tutorial009c_py310.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
And then you won't have to worry about names like `Optional` and `Union`. 😎
|
||||||
|
|
||||||
#### Generic types
|
#### Generic types
|
||||||
|
|
||||||
These types that take type parameters in square brackets are called **Generic types** or **Generics**, for example:
|
These types that take type parameters in square brackets are called **Generic types** or **Generics**, for example:
|
||||||
|
|
@ -333,7 +372,7 @@ These types that take type parameters in square brackets are called **Generic ty
|
||||||
|
|
||||||
=== "Python 3.9 and above"
|
=== "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`
|
* `list`
|
||||||
* `tuple`
|
* `tuple`
|
||||||
|
|
@ -348,7 +387,7 @@ These types that take type parameters in square brackets are called **Generic ty
|
||||||
|
|
||||||
=== "Python 3.10 and above"
|
=== "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`
|
* `list`
|
||||||
* `tuple`
|
* `tuple`
|
||||||
|
|
@ -422,6 +461,9 @@ An example from the official Pydantic docs:
|
||||||
|
|
||||||
You will see a lot more of all this in practice in the [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}.
|
You will see a lot more of all this in practice in the [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}.
|
||||||
|
|
||||||
|
!!! tip
|
||||||
|
Pydantic has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about <a href="https://pydantic-docs.helpmanual.io/usage/models/#required-optional-fields" class="external-link" target="_blank">Required Optional fields</a>.
|
||||||
|
|
||||||
## Type hints in **FastAPI**
|
## Type hints in **FastAPI**
|
||||||
|
|
||||||
**FastAPI** takes advantage of these type hints to do several things.
|
**FastAPI** takes advantage of these type hints to do several things.
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,454 @@
|
||||||
|
|
||||||
## Latest Changes
|
## Latest Changes
|
||||||
|
|
||||||
|
* 🌐 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).
|
||||||
|
* ⬆ 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).
|
||||||
|
* 🌐 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 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).
|
||||||
|
* ⬆ 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 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).
|
||||||
|
* ⬆ 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).
|
||||||
|
* 🌐 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).
|
||||||
|
* 📝 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).
|
||||||
|
* 🌐 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).
|
||||||
|
* 🐛 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
|
||||||
|
|
||||||
|
* 🐛 Fix `response_model` not invalidating `None`. PR [#2725](https://github.com/tiangolo/fastapi/pull/2725) by [@hukkin](https://github.com/hukkin).
|
||||||
|
|
||||||
|
If you are using `response_model` with some type that doesn't include `None` but the function is returning `None`, it will now raise an internal server error, because you are returning invalid data that violates the contract in `response_model`. Before this release it would allow breaking that contract returning `None`.
|
||||||
|
|
||||||
|
For example, if you have an app like this:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
class Item(BaseModel):
|
||||||
|
name: str
|
||||||
|
price: Optional[float] = None
|
||||||
|
owner_ids: Optional[List[int]] = None
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
@app.get("/items/invalidnone", response_model=Item)
|
||||||
|
def get_invalid_none():
|
||||||
|
return None
|
||||||
|
```
|
||||||
|
|
||||||
|
...calling the path `/items/invalidnone` will raise an error, because `None` is not a valid type for the `response_model` declared with `Item`.
|
||||||
|
|
||||||
|
You could also be implicitly returning `None` without realizing, for example:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
class Item(BaseModel):
|
||||||
|
name: str
|
||||||
|
price: Optional[float] = None
|
||||||
|
owner_ids: Optional[List[int]] = None
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
@app.get("/items/invalidnone", response_model=Item)
|
||||||
|
def get_invalid_none():
|
||||||
|
if flag:
|
||||||
|
return {"name": "foo"}
|
||||||
|
# if flag is False, at this point the function will implicitly return None
|
||||||
|
```
|
||||||
|
|
||||||
|
If you have *path operations* using `response_model` that need to be allowed to return `None`, make it explicit in `response_model` using `Union[Something, None]`:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
class Item(BaseModel):
|
||||||
|
name: str
|
||||||
|
price: Optional[float] = None
|
||||||
|
owner_ids: Optional[List[int]] = None
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
@app.get("/items/invalidnone", response_model=Union[Item, None])
|
||||||
|
def get_invalid_none():
|
||||||
|
return None
|
||||||
|
```
|
||||||
|
|
||||||
|
This way the data will be correctly validated, you won't have an internal server error, and the documentation will also reflect that this *path operation* could return `None` (or `null` in JSON).
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* ⬆ Upgrade Swagger UI copy of `oauth2-redirect.html` to include fixes for flavors of authorization code flows in Swagger UI. PR [#3439](https://github.com/tiangolo/fastapi/pull/3439) initial PR by [@koonpeng](https://github.com/koonpeng).
|
||||||
|
* ♻ Strip empty whitespace from description extracted from docstrings. PR [#2821](https://github.com/tiangolo/fastapi/pull/2821) by [@and-semakin](https://github.com/and-semakin).
|
||||||
|
* 🐛 Fix cached dependencies when using a dependency in `Security()` and other places (e.g. `Depends()`) with different OAuth2 scopes. PR [#2945](https://github.com/tiangolo/fastapi/pull/2945) by [@laggardkernel](https://github.com/laggardkernel).
|
||||||
|
* 🎨 Update type annotations for `response_model`, allow things like `Union[str, None]`. PR [#5294](https://github.com/tiangolo/fastapi/pull/5294) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
|
||||||
|
### Translations
|
||||||
|
|
||||||
|
* 🌐 Fix typos in German translation for `docs/de/docs/features.md`. PR [#4533](https://github.com/tiangolo/fastapi/pull/4533) by [@0xflotus](https://github.com/0xflotus).
|
||||||
|
* 🌐 Add missing navigator for `encoder.md` in Korean translation. PR [#5238](https://github.com/tiangolo/fastapi/pull/5238) by [@joonas-yoon](https://github.com/joonas-yoon).
|
||||||
|
* (Empty PR merge by accident) [#4913](https://github.com/tiangolo/fastapi/pull/4913).
|
||||||
|
|
||||||
|
## 0.79.1
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* 🐛 Fix `jsonable_encoder` using `include` and `exclude` parameters for non-Pydantic objects. PR [#2606](https://github.com/tiangolo/fastapi/pull/2606) by [@xaviml](https://github.com/xaviml).
|
||||||
|
* 🐛 Fix edge case with repeated aliases names not shown in OpenAPI. PR [#2351](https://github.com/tiangolo/fastapi/pull/2351) by [@klaa97](https://github.com/klaa97).
|
||||||
|
* 📝 Add misc dependency installs to tutorial docs. PR [#2126](https://github.com/tiangolo/fastapi/pull/2126) by [@TeoZosa](https://github.com/TeoZosa).
|
||||||
|
|
||||||
|
### Docs
|
||||||
|
|
||||||
|
* 📝 Add note giving credit for illustrations to [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot/). PR [#5284](https://github.com/tiangolo/fastapi/pull/5284) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* ✏ Fix typo in `python-types.md`. PR [#5116](https://github.com/tiangolo/fastapi/pull/5116) by [@Kludex](https://github.com/Kludex).
|
||||||
|
* ✏ Fix typo in `docs/en/docs/python-types.md`. PR [#5007](https://github.com/tiangolo/fastapi/pull/5007) by [@atiabbz](https://github.com/atiabbz).
|
||||||
|
* 📝 Remove unneeded Django/Flask references from async topic intro. PR [#5280](https://github.com/tiangolo/fastapi/pull/5280) by [@carltongibson](https://github.com/carltongibson).
|
||||||
|
* ✨ Add illustrations for Concurrent burgers and Parallel burgers. PR [#5277](https://github.com/tiangolo/fastapi/pull/5277) by [@tiangolo](https://github.com/tiangolo). Updated docs at: [Concurrency and Burgers](https://fastapi.tiangolo.com/async/#concurrency-and-burgers).
|
||||||
|
|
||||||
|
### Translations
|
||||||
|
|
||||||
|
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/query-params.md`. PR [#4775](https://github.com/tiangolo/fastapi/pull/4775) by [@batlopes](https://github.com/batlopes).
|
||||||
|
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/security/first-steps.md`. PR [#4954](https://github.com/tiangolo/fastapi/pull/4954) by [@FLAIR7](https://github.com/FLAIR7).
|
||||||
|
* 🌐 Add translation for `docs/zh/docs/advanced/response-cookies.md`. PR [#4638](https://github.com/tiangolo/fastapi/pull/4638) by [@zhangbo2012](https://github.com/zhangbo2012).
|
||||||
|
* 🌐 Add French translation for `docs/fr/docs/deployment/index.md`. PR [#3689](https://github.com/tiangolo/fastapi/pull/3689) by [@rjNemo](https://github.com/rjNemo).
|
||||||
|
* 🌐 Add Portuguese translation for `tutorial/handling-errors.md`. PR [#4769](https://github.com/tiangolo/fastapi/pull/4769) by [@frnsimoes](https://github.com/frnsimoes).
|
||||||
|
* 🌐 Add French translation for `docs/fr/docs/history-design-future.md`. PR [#3451](https://github.com/tiangolo/fastapi/pull/3451) by [@rjNemo](https://github.com/rjNemo).
|
||||||
|
* 🌐 Add Russian translation for `docs/ru/docs/tutorial/background-tasks.md`. PR [#4854](https://github.com/tiangolo/fastapi/pull/4854) by [@AdmiralDesu](https://github.com/AdmiralDesu).
|
||||||
|
* 🌐 Add Chinese translation for `docs/tutorial/security/first-steps.md`. PR [#3841](https://github.com/tiangolo/fastapi/pull/3841) by [@jaystone776](https://github.com/jaystone776).
|
||||||
|
* 🌐 Add Japanese translation for `docs/ja/docs/advanced/nosql-databases.md`. PR [#4205](https://github.com/tiangolo/fastapi/pull/4205) by [@sUeharaE4](https://github.com/sUeharaE4).
|
||||||
|
* 🌐 Add Indonesian translation for `docs/id/docs/tutorial/index.md`. PR [#4705](https://github.com/tiangolo/fastapi/pull/4705) by [@bas-baskara](https://github.com/bas-baskara).
|
||||||
|
* 🌐 Add Persian translation for `docs/fa/docs/index.md` and tweak right-to-left CSS. PR [#2395](https://github.com/tiangolo/fastapi/pull/2395) by [@mohsen-mahmoodi](https://github.com/mohsen-mahmoodi).
|
||||||
|
|
||||||
|
### Internal
|
||||||
|
|
||||||
|
* 🔧 Update Jina sponsorship. PR [#5283](https://github.com/tiangolo/fastapi/pull/5283) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 🔧 Update Jina sponsorship. PR [#5272](https://github.com/tiangolo/fastapi/pull/5272) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 🔧 Update sponsors, Striveworks badge. PR [#5179](https://github.com/tiangolo/fastapi/pull/5179) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
|
||||||
|
## 0.79.0
|
||||||
|
|
||||||
|
### Fixes - Breaking Changes
|
||||||
|
|
||||||
|
* 🐛 Fix removing body from status codes that do not support it. PR [#5145](https://github.com/tiangolo/fastapi/pull/5145) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* Setting `status_code` to `204`, `304`, or any code below `200` (1xx) will remove the body from the response.
|
||||||
|
* This fixes an error in Uvicorn that otherwise would be thrown: `RuntimeError: Response content longer than Content-Length`.
|
||||||
|
* This removes `fastapi.openapi.constants.STATUS_CODES_WITH_NO_BODY`, it is replaced by a function in utils.
|
||||||
|
|
||||||
|
### Translations
|
||||||
|
|
||||||
|
* 🌐 Start of Hebrew translation. PR [#5050](https://github.com/tiangolo/fastapi/pull/5050) by [@itay-raveh](https://github.com/itay-raveh).
|
||||||
|
* 🔧 Add config for Swedish translations notification. PR [#5147](https://github.com/tiangolo/fastapi/pull/5147) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 🌐 Start of Swedish translation. PR [#5062](https://github.com/tiangolo/fastapi/pull/5062) by [@MrRawbin](https://github.com/MrRawbin).
|
||||||
|
* 🌐 Add Japanese translation for `docs/ja/docs/advanced/index.md`. PR [#5043](https://github.com/tiangolo/fastapi/pull/5043) by [@wakabame](https://github.com/wakabame).
|
||||||
|
* 🌐🇵🇱 Add Polish translation for `docs/pl/docs/tutorial/first-steps.md`. PR [#5024](https://github.com/tiangolo/fastapi/pull/5024) by [@Valaraucoo](https://github.com/Valaraucoo).
|
||||||
|
|
||||||
|
### Internal
|
||||||
|
|
||||||
|
* 🔧 Update translations notification for Hebrew. PR [#5158](https://github.com/tiangolo/fastapi/pull/5158) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 🔧 Update Dependabot commit message. PR [#5156](https://github.com/tiangolo/fastapi/pull/5156) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* ⬆ Bump actions/upload-artifact from 2 to 3. PR [#5148](https://github.com/tiangolo/fastapi/pull/5148) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||||
|
* ⬆ Bump actions/cache from 2 to 3. PR [#5149](https://github.com/tiangolo/fastapi/pull/5149) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||||
|
* 🔧 Update sponsors badge configs. PR [#5155](https://github.com/tiangolo/fastapi/pull/5155) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 👥 Update FastAPI People. PR [#5154](https://github.com/tiangolo/fastapi/pull/5154) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 🔧 Update Jina sponsor badges. PR [#5151](https://github.com/tiangolo/fastapi/pull/5151) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* ⬆ Bump actions/checkout from 2 to 3. PR [#5133](https://github.com/tiangolo/fastapi/pull/5133) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||||
|
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5030](https://github.com/tiangolo/fastapi/pull/5030) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
|
||||||
|
* ⬆ Bump nwtgck/actions-netlify from 1.1.5 to 1.2.3. PR [#5132](https://github.com/tiangolo/fastapi/pull/5132) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||||
|
* ⬆ Bump codecov/codecov-action from 2 to 3. PR [#5131](https://github.com/tiangolo/fastapi/pull/5131) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||||
|
* ⬆ Bump dawidd6/action-download-artifact from 2.9.0 to 2.21.1. PR [#5130](https://github.com/tiangolo/fastapi/pull/5130) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||||
|
* ⬆ Bump actions/setup-python from 2 to 4. PR [#5129](https://github.com/tiangolo/fastapi/pull/5129) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||||
|
* 👷 Add Dependabot. PR [#5128](https://github.com/tiangolo/fastapi/pull/5128) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* ♻️ Move from `Optional[X]` to `Union[X, None]` for internal utils. PR [#5124](https://github.com/tiangolo/fastapi/pull/5124) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 🔧 Update sponsors, remove Dropbase, add Doist. PR [#5096](https://github.com/tiangolo/fastapi/pull/5096) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 🔧 Update sponsors, remove Classiq, add ImgWhale. PR [#5079](https://github.com/tiangolo/fastapi/pull/5079) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
|
||||||
|
## 0.78.0
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* ✨ Add support for omitting `...` as default value when declaring required parameters with:
|
||||||
|
|
||||||
|
* `Path()`
|
||||||
|
* `Query()`
|
||||||
|
* `Header()`
|
||||||
|
* `Cookie()`
|
||||||
|
* `Body()`
|
||||||
|
* `Form()`
|
||||||
|
* `File()`
|
||||||
|
|
||||||
|
New docs at [Tutorial - Query Parameters and String Validations - Make it required](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#make-it-required). PR [#4906](https://github.com/tiangolo/fastapi/pull/4906) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
|
||||||
|
Up to now, declaring a required parameter while adding additional validation or metadata needed using `...` (Ellipsis).
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
from fastapi import Cookie, FastAPI, Header, Path, Query
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/items/{item_id}")
|
||||||
|
def main(
|
||||||
|
item_id: int = Path(default=..., gt=0),
|
||||||
|
query: str = Query(default=..., max_length=10),
|
||||||
|
session: str = Cookie(default=..., min_length=3),
|
||||||
|
x_trace: str = Header(default=..., title="Tracing header"),
|
||||||
|
):
|
||||||
|
return {"message": "Hello World"}
|
||||||
|
```
|
||||||
|
|
||||||
|
...all these parameters are required because the default value is `...` (Ellipsis).
|
||||||
|
|
||||||
|
But now it's possible and supported to just omit the default value, as would be done with Pydantic fields, and the parameters would still be required.
|
||||||
|
|
||||||
|
✨ For example, this is now supported:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
from fastapi import Cookie, FastAPI, Header, Path, Query
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/items/{item_id}")
|
||||||
|
def main(
|
||||||
|
item_id: int = Path(gt=0),
|
||||||
|
query: str = Query(max_length=10),
|
||||||
|
session: str = Cookie(min_length=3),
|
||||||
|
x_trace: str = Header(title="Tracing header"),
|
||||||
|
):
|
||||||
|
return {"message": "Hello World"}
|
||||||
|
```
|
||||||
|
|
||||||
|
To declare parameters as optional (not required), you can set a default value as always, for example using `None`:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
from typing import Union
|
||||||
|
from fastapi import Cookie, FastAPI, Header, Path, Query
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/items/{item_id}")
|
||||||
|
def main(
|
||||||
|
item_id: int = Path(gt=0),
|
||||||
|
query: Union[str, None] = Query(default=None, max_length=10),
|
||||||
|
session: Union[str, None] = Cookie(default=None, min_length=3),
|
||||||
|
x_trace: Union[str, None] = Header(default=None, title="Tracing header"),
|
||||||
|
):
|
||||||
|
return {"message": "Hello World"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docs
|
||||||
|
|
||||||
|
* 📝 Add docs recommending `Union` over `Optional` and migrate source examples. New docs at [Python Types Intro - Using `Union` or `Optional`](https://fastapi.tiangolo.com/python-types/#using-union-or-optional). PR [#4908](https://github.com/tiangolo/fastapi/pull/4908) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 🎨 Fix default value as set in tutorial for Path Operations Advanced Configurations. PR [#4899](https://github.com/tiangolo/fastapi/pull/4899) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 📝 Add documentation for redefined path operations. PR [#4864](https://github.com/tiangolo/fastapi/pull/4864) by [@madkinsz](https://github.com/madkinsz).
|
||||||
|
* 📝 Updates links for Celery documentation. PR [#4736](https://github.com/tiangolo/fastapi/pull/4736) by [@sammyzord](https://github.com/sammyzord).
|
||||||
|
* ✏ Fix example code with sets in tutorial for body nested models. PR [#3030](https://github.com/tiangolo/fastapi/pull/3030) by [@hitrust](https://github.com/hitrust).
|
||||||
|
* ✏ Fix links to Pydantic docs. PR [#4670](https://github.com/tiangolo/fastapi/pull/4670) by [@kinuax](https://github.com/kinuax).
|
||||||
|
* 📝 Update docs about Swagger UI self-hosting with newer source links. PR [#4813](https://github.com/tiangolo/fastapi/pull/4813) by [@Kastakin](https://github.com/Kastakin).
|
||||||
|
* 📝 Add link to external article: Building the Poll App From Django Tutorial With FastAPI And React. PR [#4778](https://github.com/tiangolo/fastapi/pull/4778) by [@jbrocher](https://github.com/jbrocher).
|
||||||
|
* 📝 Add OpenAPI warning to "Body - Fields" docs with extra schema extensions. PR [#4846](https://github.com/tiangolo/fastapi/pull/4846) by [@ml-evs](https://github.com/ml-evs).
|
||||||
|
|
||||||
|
### Translations
|
||||||
|
|
||||||
|
* 🌐 Fix code examples in Japanese translation for `docs/ja/docs/tutorial/testing.md`. PR [#4623](https://github.com/tiangolo/fastapi/pull/4623) by [@hirotoKirimaru](https://github.com/hirotoKirimaru).
|
||||||
|
|
||||||
|
### Internal
|
||||||
|
|
||||||
|
* ♻ Refactor dict value extraction to minimize key lookups `fastapi/utils.py`. PR [#3139](https://github.com/tiangolo/fastapi/pull/3139) by [@ShahriyarR](https://github.com/ShahriyarR).
|
||||||
|
* ✅ Add tests for required nonable parameters and body fields. PR [#4907](https://github.com/tiangolo/fastapi/pull/4907) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 👷 Fix installing Material for MkDocs Insiders in CI. PR [#4897](https://github.com/tiangolo/fastapi/pull/4897) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 👷 Add pre-commit CI instead of custom GitHub Action. PR [#4896](https://github.com/tiangolo/fastapi/pull/4896) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 👷 Add pre-commit GitHub Action workflow. PR [#4895](https://github.com/tiangolo/fastapi/pull/4895) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 📝 Add dark mode auto switch to docs based on OS preference. PR [#4869](https://github.com/tiangolo/fastapi/pull/4869) by [@ComicShrimp](https://github.com/ComicShrimp).
|
||||||
|
* 🔥 Remove un-used old pending tests, already covered in other places. PR [#4891](https://github.com/tiangolo/fastapi/pull/4891) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 🔧 Add Python formatting hooks to pre-commit. PR [#4890](https://github.com/tiangolo/fastapi/pull/4890) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 🔧 Add pre-commit with first config and first formatting pass. PR [#4888](https://github.com/tiangolo/fastapi/pull/4888) by [@tiangolo](https://github.com/tiangolo).
|
||||||
|
* 👷 Disable CI installing Material for MkDocs in forks. PR [#4410](https://github.com/tiangolo/fastapi/pull/4410) by [@dolfinus](https://github.com/dolfinus).
|
||||||
|
|
||||||
## 0.77.1
|
## 0.77.1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ You can see more details in <a href="https://www.starlette.io/background/" class
|
||||||
|
|
||||||
## Caveat
|
## Caveat
|
||||||
|
|
||||||
If you need to perform heavy background computation and you don't necessarily need it to be run by the same process (for example, you don't need to share memory, variables, etc), you might benefit from using other bigger tools like <a href="https://docs.celeryproject.org" class="external-link" target="_blank">Celery</a>.
|
If you need to perform heavy background computation and you don't necessarily need it to be run by the same process (for example, you don't need to share memory, variables, etc), you might benefit from using other bigger tools like <a href="https://docs.celeryq.dev" class="external-link" target="_blank">Celery</a>.
|
||||||
|
|
||||||
They tend to require more complex configurations, a message/job queue manager, like RabbitMQ or Redis, but they allow you to run background tasks in multiple processes, and especially, in multiple servers.
|
They tend to require more complex configurations, a message/job queue manager, like RabbitMQ or Redis, but they allow you to run background tasks in multiple processes, and especially, in multiple servers.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,10 @@ You can declare extra information in `Field`, `Query`, `Body`, etc. And it will
|
||||||
|
|
||||||
You will learn more about adding extra information later in the docs, when learning to declare examples.
|
You will learn more about adding extra information later in the docs, when learning to declare examples.
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
Extra keys passed to `Field` will also be present in the resulting OpenAPI schema for your application.
|
||||||
|
As these keys may not necessarily be part of the OpenAPI specification, some OpenAPI tools, for example [the OpenAPI validator](https://validator.swagger.io/), may not work with your generated schema.
|
||||||
|
|
||||||
## Recap
|
## Recap
|
||||||
|
|
||||||
You can use Pydantic's `Field` to declare extra validations and metadata for model attributes.
|
You can use Pydantic's `Field` to declare extra validations and metadata for model attributes.
|
||||||
|
|
|
||||||
|
|
@ -89,13 +89,13 @@ But you can instruct **FastAPI** to treat it as another body key using `Body`:
|
||||||
|
|
||||||
=== "Python 3.6 and above"
|
=== "Python 3.6 and above"
|
||||||
|
|
||||||
```Python hl_lines="23"
|
```Python hl_lines="22"
|
||||||
{!> ../../../docs_src/body_multiple_params/tutorial003.py!}
|
{!> ../../../docs_src/body_multiple_params/tutorial003.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python 3.10 and above"
|
=== "Python 3.10 and above"
|
||||||
|
|
||||||
```Python hl_lines="21"
|
```Python hl_lines="20"
|
||||||
{!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!}
|
{!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -126,7 +126,7 @@ Of course, you can also declare additional query parameters whenever you need, a
|
||||||
As, by default, singular values are interpreted as query parameters, you don't have to explicitly add a `Query`, you can just do:
|
As, by default, singular values are interpreted as query parameters, you don't have to explicitly add a `Query`, you can just do:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
q: Optional[str] = None
|
q: Union[str, None] = None
|
||||||
```
|
```
|
||||||
|
|
||||||
Or in Python 3.10 and above:
|
Or in Python 3.10 and above:
|
||||||
|
|
@ -139,7 +139,7 @@ For example:
|
||||||
|
|
||||||
=== "Python 3.6 and above"
|
=== "Python 3.6 and above"
|
||||||
|
|
||||||
```Python hl_lines="28"
|
```Python hl_lines="27"
|
||||||
{!> ../../../docs_src/body_multiple_params/tutorial004.py!}
|
{!> ../../../docs_src/body_multiple_params/tutorial004.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -152,7 +152,6 @@ For example:
|
||||||
!!! info
|
!!! info
|
||||||
`Body` also has all the same extra validation and metadata parameters as `Query`,`Path` and others you will see later.
|
`Body` also has all the same extra validation and metadata parameters as `Query`,`Path` and others you will see later.
|
||||||
|
|
||||||
|
|
||||||
## Embed a single body parameter
|
## Embed a single body parameter
|
||||||
|
|
||||||
Let's say you only have a single `item` body parameter from a Pydantic model `Item`.
|
Let's say you only have a single `item` body parameter from a Pydantic model `Item`.
|
||||||
|
|
@ -162,7 +161,7 @@ By default, **FastAPI** will then expect its body directly.
|
||||||
But if you want it to expect a JSON with a key `item` and inside of it the model contents, as it does when you declare extra body parameters, you can use the special `Body` parameter `embed`:
|
But if you want it to expect a JSON with a key `item` and inside of it the model contents, as it does when you declare extra body parameters, you can use the special `Body` parameter `embed`:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
item: Item = Body(..., embed=True)
|
item: Item = Body(embed=True)
|
||||||
```
|
```
|
||||||
|
|
||||||
as in:
|
as in:
|
||||||
|
|
|
||||||
|
|
@ -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!}
|
{!> ../../../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
|
## List fields with type parameter
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ The function parameters will be recognized as follows:
|
||||||
!!! note
|
!!! note
|
||||||
FastAPI will know that the value of `q` is not required because of the default value `= None`.
|
FastAPI will know that the value of `q` is not required because of the default value `= None`.
|
||||||
|
|
||||||
The `Optional` in `Optional[str]` is not used by FastAPI, but will allow your editor to give you better support and detect errors.
|
The `Union` in `Union[str, None]` is not used by FastAPI, but will allow your editor to give you better support and detect errors.
|
||||||
|
|
||||||
## Without Pydantic
|
## Without Pydantic
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ Pay attention to the `__init__` method used to create the instance of the class:
|
||||||
|
|
||||||
=== "Python 3.6 and above"
|
=== "Python 3.6 and above"
|
||||||
|
|
||||||
```Python hl_lines="8"
|
```Python hl_lines="9"
|
||||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ It is just a function that can take all the same parameters that a *path operati
|
||||||
|
|
||||||
=== "Python 3.6 and above"
|
=== "Python 3.6 and above"
|
||||||
|
|
||||||
```Python hl_lines="8-9"
|
```Python hl_lines="8-11"
|
||||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -81,7 +81,7 @@ The same way you use `Body`, `Query`, etc. with your *path operation function* p
|
||||||
|
|
||||||
=== "Python 3.6 and above"
|
=== "Python 3.6 and above"
|
||||||
|
|
||||||
```Python hl_lines="13 18"
|
```Python hl_lines="15 20"
|
||||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ Then we can use the dependency with:
|
||||||
|
|
||||||
=== "Python 3.6 and above"
|
=== "Python 3.6 and above"
|
||||||
|
|
||||||
```Python hl_lines="21"
|
```Python hl_lines="22"
|
||||||
{!> ../../../docs_src/dependencies/tutorial005.py!}
|
{!> ../../../docs_src/dependencies/tutorial005.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ Here are some of the additional data types you can use:
|
||||||
* `datetime.timedelta`:
|
* `datetime.timedelta`:
|
||||||
* A Python `datetime.timedelta`.
|
* A Python `datetime.timedelta`.
|
||||||
* In requests and responses will be represented as a `float` of total seconds.
|
* In requests and responses will be represented as a `float` of total seconds.
|
||||||
* Pydantic also allows representing it as a "ISO 8601 time diff encoding", <a href="https://pydantic-docs.helpmanual.io/#json-serialisation" class="external-link" target="_blank">see the docs for more info</a>.
|
* Pydantic also allows representing it as a "ISO 8601 time diff encoding", <a href="https://pydantic-docs.helpmanual.io/usage/exporting_models/#json_encoders" class="external-link" target="_blank">see the docs for more info</a>.
|
||||||
* `frozenset`:
|
* `frozenset`:
|
||||||
* In requests and responses, treated the same as a `set`:
|
* In requests and responses, treated the same as a `set`:
|
||||||
* In requests, a list will be read, eliminating duplicates and converting it to a `set`.
|
* In requests, a list will be read, eliminating duplicates and converting it to a `set`.
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ path -> item_id
|
||||||
!!! warning
|
!!! warning
|
||||||
These are technical details that you might skip if it's not important for you now.
|
These are technical details that you might skip if it's not important for you now.
|
||||||
|
|
||||||
`RequestValidationError` is a sub-class of Pydantic's <a href="https://pydantic-docs.helpmanual.io/#error-handling" class="external-link" target="_blank">`ValidationError`</a>.
|
`RequestValidationError` is a sub-class of Pydantic's <a href="https://pydantic-docs.helpmanual.io/usage/models/#error-handling" class="external-link" target="_blank">`ValidationError`</a>.
|
||||||
|
|
||||||
**FastAPI** uses it so that, if you use a Pydantic model in `response_model`, and your data has an error, you will see the error in your log.
|
**FastAPI** uses it so that, if you use a Pydantic model in `response_model`, and your data has an error, you will see the error in your log.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Path Parameters and Numeric Validations
|
# 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
|
## Import Path
|
||||||
|
|
||||||
|
|
@ -59,7 +59,7 @@ It doesn't matter for **FastAPI**. It will detect the parameters by their names,
|
||||||
|
|
||||||
So, you can declare your function as:
|
So, you can declare your function as:
|
||||||
|
|
||||||
```Python hl_lines="8"
|
```Python hl_lines="7"
|
||||||
{!../../../docs_src/path_params_numeric_validations/tutorial002.py!}
|
{!../../../docs_src/path_params_numeric_validations/tutorial002.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -71,13 +71,13 @@ Pass `*`, as the first parameter of the function.
|
||||||
|
|
||||||
Python won't do anything with that `*`, but it will know that all the following parameters should be called as keyword arguments (key-value pairs), also known as <abbr title="From: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>. Even if they don't have a default value.
|
Python won't do anything with that `*`, but it will know that all the following parameters should be called as keyword arguments (key-value pairs), also known as <abbr title="From: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>. Even if they don't have a default value.
|
||||||
|
|
||||||
```Python hl_lines="8"
|
```Python hl_lines="7"
|
||||||
{!../../../docs_src/path_params_numeric_validations/tutorial003.py!}
|
{!../../../docs_src/path_params_numeric_validations/tutorial003.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Number validations: greater than or equal
|
## 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`.
|
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
|
* `le`: `l`ess than or `e`qual
|
||||||
|
|
||||||
!!! info
|
!!! 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"
|
!!! note "Technical Details"
|
||||||
When you import `Query`, `Path` and others from `fastapi`, they are actually functions.
|
When you import `Query`, `Path` and others from `fastapi`, they are actually functions.
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,14 @@ Because *path operations* are evaluated in order, you need to make sure that the
|
||||||
|
|
||||||
Otherwise, the path for `/users/{user_id}` would match also for `/users/me`, "thinking" that it's receiving a parameter `user_id` with a value of `"me"`.
|
Otherwise, the path for `/users/{user_id}` would match also for `/users/me`, "thinking" that it's receiving a parameter `user_id` with a value of `"me"`.
|
||||||
|
|
||||||
|
Similarly, you cannot redefine a path operation:
|
||||||
|
|
||||||
|
```Python hl_lines="6 11"
|
||||||
|
{!../../../docs_src/path_params/tutorial003b.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
The first one will always be used since the path matches first.
|
||||||
|
|
||||||
## Predefined values
|
## Predefined values
|
||||||
|
|
||||||
If you have a *path operation* that receives a *path parameter*, but you want the possible valid *path parameter* values to be predefined, you can use a standard Python <abbr title="Enumeration">`Enum`</abbr>.
|
If you have a *path operation* that receives a *path parameter*, but you want the possible valid *path parameter* values to be predefined, you can use a standard Python <abbr title="Enumeration">`Enum`</abbr>.
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,12 @@ Let's take this application as example:
|
||||||
{!> ../../../docs_src/query_params_str_validations/tutorial001_py310.py!}
|
{!> ../../../docs_src/query_params_str_validations/tutorial001_py310.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
The query parameter `q` is of type `Optional[str]` (or `str | None` in Python 3.10), that means that it's of type `str` but could also be `None`, and indeed, the default value is `None`, so FastAPI will know it's not required.
|
The query parameter `q` is of type `Union[str, None]` (or `str | None` in Python 3.10), that means that it's of type `str` but could also be `None`, and indeed, the default value is `None`, so FastAPI will know it's not required.
|
||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
FastAPI will know that the value of `q` is not required because of the default value `= None`.
|
FastAPI will know that the value of `q` is not required because of the default value `= None`.
|
||||||
|
|
||||||
The `Optional` in `Optional[str]` is not used by FastAPI, but will allow your editor to give you better support and detect errors.
|
The `Union` in `Union[str, None]` will allow your editor to give you better support and detect errors.
|
||||||
|
|
||||||
## Additional validation
|
## Additional validation
|
||||||
|
|
||||||
|
|
@ -59,24 +59,24 @@ And now use it as the default value of your parameter, setting the parameter `ma
|
||||||
{!> ../../../docs_src/query_params_str_validations/tutorial002_py310.py!}
|
{!> ../../../docs_src/query_params_str_validations/tutorial002_py310.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
As we have to replace the default value `None` with `Query(None)`, the first parameter to `Query` serves the same purpose of defining that default value.
|
As we have to replace the default value `None` in the function with `Query()`, we can now set the default value with the parameter `Query(default=None)`, it serves the same purpose of defining that default value.
|
||||||
|
|
||||||
So:
|
So:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
q: Optional[str] = Query(None)
|
q: Union[str, None] = Query(default=None)
|
||||||
```
|
```
|
||||||
|
|
||||||
...makes the parameter optional, the same as:
|
...makes the parameter optional, the same as:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
q: Optional[str] = None
|
q: Union[str, None] = None
|
||||||
```
|
```
|
||||||
|
|
||||||
And in Python 3.10 and above:
|
And in Python 3.10 and above:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
q: str | None = Query(None)
|
q: str | None = Query(default=None)
|
||||||
```
|
```
|
||||||
|
|
||||||
...makes the parameter optional, the same as:
|
...makes the parameter optional, the same as:
|
||||||
|
|
@ -97,17 +97,17 @@ But it declares it explicitly as being a query parameter.
|
||||||
or the:
|
or the:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
= Query(None)
|
= Query(default=None)
|
||||||
```
|
```
|
||||||
|
|
||||||
as it will use that `None` as the default value, and that way make the parameter **not required**.
|
as it will use that `None` as the default value, and that way make the parameter **not required**.
|
||||||
|
|
||||||
The `Optional` part allows your editor to provide better support, but it is not what tells FastAPI that this parameter is not required.
|
The `Union[str, None]` part allows your editor to provide better support, but it is not what tells FastAPI that this parameter is not required.
|
||||||
|
|
||||||
Then, we can pass more parameters to `Query`. In this case, the `max_length` parameter that applies to strings:
|
Then, we can pass more parameters to `Query`. In this case, the `max_length` parameter that applies to strings:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
q: str = Query(None, max_length=50)
|
q: Union[str, None] = Query(default=None, max_length=50)
|
||||||
```
|
```
|
||||||
|
|
||||||
This will validate the data, show a clear error when the data is not valid, and document the parameter in the OpenAPI schema *path operation*.
|
This will validate the data, show a clear error when the data is not valid, and document the parameter in the OpenAPI schema *path operation*.
|
||||||
|
|
@ -118,7 +118,7 @@ You can also add a parameter `min_length`:
|
||||||
|
|
||||||
=== "Python 3.6 and above"
|
=== "Python 3.6 and above"
|
||||||
|
|
||||||
```Python hl_lines="9"
|
```Python hl_lines="10"
|
||||||
{!> ../../../docs_src/query_params_str_validations/tutorial003.py!}
|
{!> ../../../docs_src/query_params_str_validations/tutorial003.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -134,13 +134,13 @@ You can define a <abbr title="A regular expression, regex or regexp is a sequenc
|
||||||
|
|
||||||
=== "Python 3.6 and above"
|
=== "Python 3.6 and above"
|
||||||
|
|
||||||
```Python hl_lines="10"
|
```Python hl_lines="11"
|
||||||
{!> ../../../docs_src/query_params_str_validations/tutorial004.py!}
|
{!> ../../../docs_src/query_params_str_validations/tutorial004.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python 3.10 and above"
|
=== "Python 3.10 and above"
|
||||||
|
|
||||||
```Python hl_lines="8"
|
```Python hl_lines="9"
|
||||||
{!> ../../../docs_src/query_params_str_validations/tutorial004_py310.py!}
|
{!> ../../../docs_src/query_params_str_validations/tutorial004_py310.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -156,7 +156,7 @@ But whenever you need them and go and learn them, know that you can already use
|
||||||
|
|
||||||
## Default values
|
## Default values
|
||||||
|
|
||||||
The same way that you can pass `None` as the first argument to be used as the default value, you can pass other values.
|
The same way that you can pass `None` as the value for the `default` parameter, you can pass other values.
|
||||||
|
|
||||||
Let's say that you want to declare the `q` query parameter to have a `min_length` of `3`, and to have a default value of `"fixedquery"`:
|
Let's say that you want to declare the `q` query parameter to have a `min_length` of `3`, and to have a default value of `"fixedquery"`:
|
||||||
|
|
||||||
|
|
@ -178,26 +178,68 @@ q: str
|
||||||
instead of:
|
instead of:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
q: Optional[str] = None
|
q: Union[str, None] = None
|
||||||
```
|
```
|
||||||
|
|
||||||
But we are now declaring it with `Query`, for example like:
|
But we are now declaring it with `Query`, for example like:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
q: Optional[str] = Query(None, min_length=3)
|
q: Union[str, None] = Query(default=None, min_length=3)
|
||||||
```
|
```
|
||||||
|
|
||||||
So, when you need to declare a value as required while using `Query`, you can use `...` as the first argument:
|
So, when you need to declare a value as required while using `Query`, you can simply not declare a default value:
|
||||||
|
|
||||||
```Python hl_lines="7"
|
```Python hl_lines="7"
|
||||||
{!../../../docs_src/query_params_str_validations/tutorial006.py!}
|
{!../../../docs_src/query_params_str_validations/tutorial006.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Required with Ellipsis (`...`)
|
||||||
|
|
||||||
|
There's an alternative way to explicitly declare that a value is required. You can set the `default` parameter to the literal value `...`:
|
||||||
|
|
||||||
|
```Python hl_lines="7"
|
||||||
|
{!../../../docs_src/query_params_str_validations/tutorial006b.py!}
|
||||||
|
```
|
||||||
|
|
||||||
!!! info
|
!!! info
|
||||||
If you hadn't seen that `...` before: it is a special single value, it is <a href="https://docs.python.org/3/library/constants.html#Ellipsis" class="external-link" target="_blank">part of Python and is called "Ellipsis"</a>.
|
If you hadn't seen that `...` before: it is a special single value, it is <a href="https://docs.python.org/3/library/constants.html#Ellipsis" class="external-link" target="_blank">part of Python and is called "Ellipsis"</a>.
|
||||||
|
|
||||||
|
It is used by Pydantic and FastAPI to explicitly declare that a value is required.
|
||||||
|
|
||||||
This will let **FastAPI** know that this parameter is required.
|
This will let **FastAPI** know that this parameter is required.
|
||||||
|
|
||||||
|
### Required with `None`
|
||||||
|
|
||||||
|
You can declare that a parameter can accept `None`, but that it's still required. This would force clients to send a value, even if the value is `None`.
|
||||||
|
|
||||||
|
To do that, you can declare that `None` is a valid type but still use `default=...`:
|
||||||
|
|
||||||
|
=== "Python 3.6 and above"
|
||||||
|
|
||||||
|
```Python hl_lines="9"
|
||||||
|
{!> ../../../docs_src/query_params_str_validations/tutorial006c.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Python 3.10 and above"
|
||||||
|
|
||||||
|
```Python hl_lines="7"
|
||||||
|
{!> ../../../docs_src/query_params_str_validations/tutorial006c_py310.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! tip
|
||||||
|
Pydantic, which is what powers all the data validation and serialization in FastAPI, has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about <a href="https://pydantic-docs.helpmanual.io/usage/models/#required-optional-fields" class="external-link" target="_blank">Required Optional fields</a>.
|
||||||
|
|
||||||
|
### Use Pydantic's `Required` instead of Ellipsis (`...`)
|
||||||
|
|
||||||
|
If you feel uncomfortable using `...`, you can also import and use `Required` from Pydantic:
|
||||||
|
|
||||||
|
```Python hl_lines="2 8"
|
||||||
|
{!../../../docs_src/query_params_str_validations/tutorial006d.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! tip
|
||||||
|
Remember that in most of the cases, when something is required, you can simply omit the `default` parameter, so you normally don't have to use `...` nor `Required`.
|
||||||
|
|
||||||
## Query parameter list / multiple values
|
## Query parameter list / multiple values
|
||||||
|
|
||||||
When you define a query parameter explicitly with `Query` you can also declare it to receive a list of values, or said in other way, to receive multiple values.
|
When you define a query parameter explicitly with `Query` you can also declare it to receive a list of values, or said in other way, to receive multiple values.
|
||||||
|
|
@ -315,7 +357,7 @@ You can add a `title`:
|
||||||
|
|
||||||
=== "Python 3.10 and above"
|
=== "Python 3.10 and above"
|
||||||
|
|
||||||
```Python hl_lines="7"
|
```Python hl_lines="8"
|
||||||
{!> ../../../docs_src/query_params_str_validations/tutorial007_py310.py!}
|
{!> ../../../docs_src/query_params_str_validations/tutorial007_py310.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -399,7 +441,7 @@ To exclude a query parameter from the generated OpenAPI schema (and thus, from t
|
||||||
|
|
||||||
=== "Python 3.10 and above"
|
=== "Python 3.10 and above"
|
||||||
|
|
||||||
```Python hl_lines="7"
|
```Python hl_lines="8"
|
||||||
{!> ../../../docs_src/query_params_str_validations/tutorial014_py310.py!}
|
{!> ../../../docs_src/query_params_str_validations/tutorial014_py310.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!}
|
{!> ../../../docs_src/request_files/tutorial001_02.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python 3.9 and above"
|
=== "Python 3.10 and above"
|
||||||
|
|
||||||
```Python hl_lines="7 14"
|
```Python hl_lines="7 14"
|
||||||
{!> ../../../docs_src/request_files/tutorial001_02_py310.py!}
|
{!> ../../../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.
|
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
|
!!! info
|
||||||
`Form` is a class that inherits directly from `Body`.
|
`Form` is a class that inherits directly from `Body`.
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,12 @@ Here we are declaring a `UserIn` model, it will contain a plaintext password:
|
||||||
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
|
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
To use `EmailStr`, first install <a href="https://github.com/JoshData/python-email-validator" class="external-link" target="_blank">`email_validator`</a>.
|
||||||
|
|
||||||
|
E.g. `pip install email-validator`
|
||||||
|
or `pip install pydantic[email]`.
|
||||||
|
|
||||||
And we are using this model to declare our input and the same model to declare our output:
|
And we are using this model to declare our input and the same model to declare our output:
|
||||||
|
|
||||||
=== "Python 3.6 and above"
|
=== "Python 3.6 and above"
|
||||||
|
|
@ -162,7 +168,7 @@ Your response model could have default values, like:
|
||||||
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
|
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
* `description: Optional[str] = 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`.
|
* `tax: float = 10.5` has a default of `10.5`.
|
||||||
* `tags: List[str] = []` as a default of an empty list: `[]`.
|
* `tags: List[str] = []` as a default of an empty list: `[]`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,13 +68,13 @@ Here we pass an `example` of the data expected in `Body()`:
|
||||||
|
|
||||||
=== "Python 3.6 and above"
|
=== "Python 3.6 and above"
|
||||||
|
|
||||||
```Python hl_lines="21-26"
|
```Python hl_lines="20-25"
|
||||||
{!> ../../../docs_src/schema_extra_example/tutorial003.py!}
|
{!> ../../../docs_src/schema_extra_example/tutorial003.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python 3.10 and above"
|
=== "Python 3.10 and above"
|
||||||
|
|
||||||
```Python hl_lines="19-24"
|
```Python hl_lines="18-23"
|
||||||
{!> ../../../docs_src/schema_extra_example/tutorial003_py310.py!}
|
{!> ../../../docs_src/schema_extra_example/tutorial003_py310.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -99,13 +99,13 @@ Each specific example `dict` in the `examples` can contain:
|
||||||
|
|
||||||
=== "Python 3.6 and above"
|
=== "Python 3.6 and above"
|
||||||
|
|
||||||
```Python hl_lines="22-48"
|
```Python hl_lines="21-47"
|
||||||
{!> ../../../docs_src/schema_extra_example/tutorial004.py!}
|
{!> ../../../docs_src/schema_extra_example/tutorial004.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python 3.10 and above"
|
=== "Python 3.10 and above"
|
||||||
|
|
||||||
```Python hl_lines="20-46"
|
```Python hl_lines="19-45"
|
||||||
{!> ../../../docs_src/schema_extra_example/tutorial004_py310.py!}
|
{!> ../../../docs_src/schema_extra_example/tutorial004_py310.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,20 @@ The file `__init__.py` is just an empty file, but it tells Python that `sql_app`
|
||||||
|
|
||||||
Now let's see what each file/module does.
|
Now let's see what each file/module does.
|
||||||
|
|
||||||
|
## Install `SQLAlchemy`
|
||||||
|
|
||||||
|
First you need to install `SQLAlchemy`:
|
||||||
|
|
||||||
|
<div class="termy">
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ pip install sqlalchemy
|
||||||
|
|
||||||
|
---> 100%
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
## Create the SQLAlchemy parts
|
## Create the SQLAlchemy parts
|
||||||
|
|
||||||
Let's refer to the file `sql_app/database.py`.
|
Let's refer to the file `sql_app/database.py`.
|
||||||
|
|
@ -317,7 +331,7 @@ Not only the IDs of those items, but all the data that we defined in the Pydanti
|
||||||
|
|
||||||
Now, in the Pydantic *models* for reading, `Item` and `User`, add an internal `Config` class.
|
Now, in the Pydantic *models* for reading, `Item` and `User`, add an internal `Config` class.
|
||||||
|
|
||||||
This <a href="https://pydantic-docs.helpmanual.io/#config" class="external-link" target="_blank">`Config`</a> class is used to provide configurations to Pydantic.
|
This <a href="https://pydantic-docs.helpmanual.io/usage/model_config/" class="external-link" target="_blank">`Config`</a> class is used to provide configurations to Pydantic.
|
||||||
|
|
||||||
In the `Config` class, set the attribute `orm_mode = True`.
|
In the `Config` class, set the attribute `orm_mode = True`.
|
||||||
|
|
||||||
|
|
@ -616,7 +630,7 @@ And as the code related to SQLAlchemy and the SQLAlchemy models lives in separat
|
||||||
|
|
||||||
The same way, you would be able to use the same SQLAlchemy models and utilities in other parts of your code that are not related to **FastAPI**.
|
The same way, you would be able to use the same SQLAlchemy models and utilities in other parts of your code that are not related to **FastAPI**.
|
||||||
|
|
||||||
For example, in a background task worker with <a href="https://docs.celeryproject.org" class="external-link" target="_blank">Celery</a>, <a href="https://python-rq.org/" class="external-link" target="_blank">RQ</a>, or <a href="https://arq-docs.helpmanual.io/" class="external-link" target="_blank">ARQ</a>.
|
For example, in a background task worker with <a href="https://docs.celeryq.dev" class="external-link" target="_blank">Celery</a>, <a href="https://python-rq.org/" class="external-link" target="_blank">RQ</a>, or <a href="https://arq-docs.helpmanual.io/" class="external-link" target="_blank">ARQ</a>.
|
||||||
|
|
||||||
## Review all the files
|
## Review all the files
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,11 @@ With it, you can use <a href="https://docs.pytest.org/" class="external-link" ta
|
||||||
|
|
||||||
## Using `TestClient`
|
## Using `TestClient`
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
To use `TestClient`, first install <a href="https://github.com/psf/requests" class="external-link" target="_blank">`requests`</a>.
|
||||||
|
|
||||||
|
E.g. `pip install requests`.
|
||||||
|
|
||||||
Import `TestClient`.
|
Import `TestClient`.
|
||||||
|
|
||||||
Create a `TestClient` by passing your **FastAPI** application to it.
|
Create a `TestClient` by passing your **FastAPI** application to it.
|
||||||
|
|
@ -45,7 +50,17 @@ And your **FastAPI** application might also be composed of several files/modules
|
||||||
|
|
||||||
### **FastAPI** app file
|
### **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
|
```Python
|
||||||
{!../../../docs_src/app_testing/main.py!}
|
{!../../../docs_src/app_testing/main.py!}
|
||||||
|
|
@ -53,18 +68,40 @@ Let's say you have a file `main.py` with your **FastAPI** app:
|
||||||
|
|
||||||
### Testing file
|
### 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!}
|
{!../../../docs_src/app_testing/test_main.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
...and have the code for the tests just like before.
|
||||||
|
|
||||||
## Testing: extended example
|
## Testing: extended example
|
||||||
|
|
||||||
Now let's extend this example and add more details to see how to test different parts.
|
Now let's extend this example and add more details to see how to test different parts.
|
||||||
|
|
||||||
### Extended **FastAPI** app file
|
### 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**.
|
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.
|
It has a `GET` operation that could return an error.
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,15 @@ theme:
|
||||||
name: material
|
name: material
|
||||||
custom_dir: overrides
|
custom_dir: overrides
|
||||||
palette:
|
palette:
|
||||||
- scheme: default
|
- media: '(prefers-color-scheme: light)'
|
||||||
|
scheme: default
|
||||||
primary: teal
|
primary: teal
|
||||||
accent: amber
|
accent: amber
|
||||||
toggle:
|
toggle:
|
||||||
icon: material/lightbulb
|
icon: material/lightbulb
|
||||||
name: Switch to light mode
|
name: Switch to light mode
|
||||||
- scheme: slate
|
- media: '(prefers-color-scheme: dark)'
|
||||||
|
scheme: slate
|
||||||
primary: teal
|
primary: teal
|
||||||
accent: amber
|
accent: amber
|
||||||
toggle:
|
toggle:
|
||||||
|
|
@ -42,6 +44,7 @@ nav:
|
||||||
- es: /es/
|
- es: /es/
|
||||||
- fa: /fa/
|
- fa: /fa/
|
||||||
- fr: /fr/
|
- fr: /fr/
|
||||||
|
- he: /he/
|
||||||
- id: /id/
|
- id: /id/
|
||||||
- it: /it/
|
- it: /it/
|
||||||
- ja: /ja/
|
- ja: /ja/
|
||||||
|
|
@ -51,6 +54,7 @@ nav:
|
||||||
- pt: /pt/
|
- pt: /pt/
|
||||||
- ru: /ru/
|
- ru: /ru/
|
||||||
- sq: /sq/
|
- sq: /sq/
|
||||||
|
- sv: /sv/
|
||||||
- tr: /tr/
|
- tr: /tr/
|
||||||
- uk: /uk/
|
- uk: /uk/
|
||||||
- zh: /zh/
|
- zh: /zh/
|
||||||
|
|
@ -178,6 +182,8 @@ markdown_extensions:
|
||||||
format: !!python/name:pymdownx.superfences.fence_code_format ''
|
format: !!python/name:pymdownx.superfences.fence_code_format ''
|
||||||
- pymdownx.tabbed:
|
- pymdownx.tabbed:
|
||||||
alternate_style: true
|
alternate_style: true
|
||||||
|
- attr_list
|
||||||
|
- md_in_html
|
||||||
extra:
|
extra:
|
||||||
analytics:
|
analytics:
|
||||||
provider: google
|
provider: google
|
||||||
|
|
@ -210,6 +216,8 @@ extra:
|
||||||
name: fa
|
name: fa
|
||||||
- link: /fr/
|
- link: /fr/
|
||||||
name: fr - français
|
name: fr - français
|
||||||
|
- link: /he/
|
||||||
|
name: he
|
||||||
- link: /id/
|
- link: /id/
|
||||||
name: id
|
name: id
|
||||||
- link: /it/
|
- link: /it/
|
||||||
|
|
@ -228,6 +236,8 @@ extra:
|
||||||
name: ru - русский язык
|
name: ru - русский язык
|
||||||
- link: /sq/
|
- link: /sq/
|
||||||
name: sq - shqip
|
name: sq - shqip
|
||||||
|
- link: /sv/
|
||||||
|
name: sv - svenska
|
||||||
- link: /tr/
|
- link: /tr/
|
||||||
name: tr - Türkçe
|
name: tr - Türkçe
|
||||||
- link: /uk/
|
- link: /uk/
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,9 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<a title="Jina: build neural search-as-a-service for any kind of data in just minutes." style="display: block; position: relative;" href="https://bit.ly/2QSouzH" target="_blank">
|
<a title="The data structure for unstructured multimodal data" style="display: block; position: relative;" href="https://bit.ly/3AcNTYL" target="_blank">
|
||||||
<span class="sponsor-badge">sponsor</span>
|
<span class="sponsor-badge">sponsor</span>
|
||||||
<img class="sponsor-image" src="/img/sponsors/jina-banner.svg" />
|
<img class="sponsor-image" src="/img/sponsors/docarray-top-banner.svg" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
|
|
@ -40,16 +40,22 @@
|
||||||
<img class="sponsor-image" src="/img/sponsors/cryptapi-banner.svg" />
|
<img class="sponsor-image" src="/img/sponsors/cryptapi-banner.svg" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<!-- <div class="item">
|
||||||
<a title="Join the team building a new SaaS platform that will change the computing world" style="display: block; position: relative;" href="https://classiq.link/mzg" target="_blank">
|
<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>
|
<span class="sponsor-badge">sponsor</span>
|
||||||
<img class="sponsor-image" src="/img/sponsors/classiq-banner.png" />
|
<img class="sponsor-image" src="/img/sponsors/imgwhale-banner.svg" />
|
||||||
|
</a>
|
||||||
|
</div> -->
|
||||||
|
<div class="item">
|
||||||
|
<a title="Help us migrate doist to FastAPI" style="display: block; position: relative;" href="https://doist.com/careers/9B437B1615-wa-senior-backend-engineer-python" target="_blank">
|
||||||
|
<span class="sponsor-badge">sponsor</span>
|
||||||
|
<img class="sponsor-image" src="/img/sponsors/doist-banner.svg" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<a title="Dropbase - seamlessly collect, clean, and centralize data." style="display: block; position: relative;" href="https://www.dropbase.io/careers" target="_blank">
|
<a title="Build cross-modal and multimodal applications on the cloud" style="display: block; position: relative;" href="https://bit.ly/3dphxRq" target="_blank">
|
||||||
<span class="sponsor-badge">sponsor</span>
|
<span class="sponsor-badge">sponsor</span>
|
||||||
<img class="sponsor-image" src="/img/sponsors/dropbase-banner.svg" />
|
<img class="sponsor-image" src="/img/sponsors/jina-top-banner.svg" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ Pero también quieres que acepte nuevos ítems. Cuando los ítems no existan ant
|
||||||
|
|
||||||
Para conseguir esto importa `JSONResponse` y devuelve ahí directamente tu contenido, asignando el `status_code` que quieras:
|
Para conseguir esto importa `JSONResponse` y devuelve ahí directamente tu contenido, asignando el `status_code` que quieras:
|
||||||
|
|
||||||
```Python hl_lines="2 19"
|
```Python hl_lines="4 25"
|
||||||
{!../../../docs_src/additional_status_codes/tutorial001.py!}
|
{!../../../docs_src/additional_status_codes/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,7 @@ Con **FastAPI** obtienes todas las características de **Pydantic** (dado que Fa
|
||||||
* Interactúa bien con tu **<abbr title="en inglés: Integrated Development Environment, similar a editor de código">IDE</abbr>/<abbr title="Un programa que chequea errores en el código">linter</abbr>/cerebro**:
|
* Interactúa bien con tu **<abbr title="en inglés: Integrated Development Environment, similar a editor de código">IDE</abbr>/<abbr title="Un programa que chequea errores en el código">linter</abbr>/cerebro**:
|
||||||
* Porque las estructuras de datos de Pydantic son solo <abbr title='En español: ejemplares. Aunque a veces los llaman incorrectamente "instancias"'>instances</abbr> de clases que tu defines, el auto-completado, el linting, mypy y tu intuición deberían funcionar bien con tus datos validados.
|
* Porque las estructuras de datos de Pydantic son solo <abbr title='En español: ejemplares. Aunque a veces los llaman incorrectamente "instancias"'>instances</abbr> de clases que tu defines, el auto-completado, el linting, mypy y tu intuición deberían funcionar bien con tus datos validados.
|
||||||
* **Rápido**:
|
* **Rápido**:
|
||||||
* En <a href="https://pydantic-docs.helpmanual.io/#benchmarks-tag" class="external-link" target="_blank">benchmarks</a> Pydantic es más rápido que todas las otras <abbr title='Herramienta, paquete. A veces llamado "librería"'>libraries</abbr> probadas.
|
* En <a href="https://pydantic-docs.helpmanual.io/benchmarks/" class="external-link" target="_blank">benchmarks</a> Pydantic es más rápido que todas las otras <abbr title='Herramienta, paquete. A veces llamado "librería"'>libraries</abbr> probadas.
|
||||||
* Valida **estructuras complejas**:
|
* Valida **estructuras complejas**:
|
||||||
* Usa modelos jerárquicos de modelos de Pydantic, `typing` de Python, `List` y `Dict`, etc.
|
* Usa modelos jerárquicos de modelos de Pydantic, `typing` de Python, `List` y `Dict`, etc.
|
||||||
* Los validadores también permiten que se definan fácil y claramente schemas complejos de datos. Estos son chequeados y documentados como JSON Schema.
|
* Los validadores también permiten que se definan fácil y claramente schemas complejos de datos. Estos son chequeados y documentados como JSON Schema.
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ Si estás construyendo un app de <abbr title="Interfaz de línea de comandos en
|
||||||
|
|
||||||
## Requisitos
|
## Requisitos
|
||||||
|
|
||||||
Python 3.6+
|
Python 3.7+
|
||||||
|
|
||||||
FastAPI está sobre los hombros de gigantes:
|
FastAPI está sobre los hombros de gigantes:
|
||||||
|
|
||||||
|
|
@ -130,7 +130,7 @@ También vas a necesitar un servidor ASGI para producción cómo <a href="https:
|
||||||
<div class="termy">
|
<div class="termy">
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ pip install uvicorn[standard]
|
$ pip install "uvicorn[standard]"
|
||||||
|
|
||||||
---> 100%
|
---> 100%
|
||||||
```
|
```
|
||||||
|
|
@ -145,7 +145,7 @@ $ pip install uvicorn[standard]
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from typing import Optional
|
from typing import Union
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
@ -156,7 +156,7 @@ def read_root():
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
def read_item(item_id: int, q: Optional[str] = None):
|
def read_item(item_id: int, q: Union[str, None] = None):
|
||||||
return {"item_id": item_id, "q": q}
|
return {"item_id": item_id, "q": q}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -167,7 +167,7 @@ Si tu código usa `async` / `await`, usa `async def`:
|
||||||
|
|
||||||
```Python hl_lines="7 12"
|
```Python hl_lines="7 12"
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from typing import Optional
|
from typing import Union
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
@ -178,7 +178,7 @@ async def read_root():
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
async def read_item(item_id: int, q: Optional[str] = None):
|
async def read_item(item_id: int, q: Union[str, None] = None):
|
||||||
return {"item_id": item_id, "q": q}
|
return {"item_id": item_id, "q": q}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -259,7 +259,7 @@ Declara el body usando las declaraciones de tipo estándares de Python gracias a
|
||||||
```Python hl_lines="2 7-10 23-25"
|
```Python hl_lines="2 7-10 23-25"
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from typing import Optional
|
from typing import Union
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
@ -267,7 +267,7 @@ app = FastAPI()
|
||||||
class Item(BaseModel):
|
class Item(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
price: float
|
price: float
|
||||||
is_offer: Optional[bool] = None
|
is_offer: Union[bool, None] = None
|
||||||
|
|
||||||
|
|
||||||
@app.get("/")
|
@app.get("/")
|
||||||
|
|
@ -276,7 +276,7 @@ def read_root():
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
def read_item(item_id: int, q: Optional[str] = None):
|
def read_item(item_id: int, q: Union[str, None] = None):
|
||||||
return {"item_id": item_id, "q": q}
|
return {"item_id": item_id, "q": q}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ Para el tutorial, es posible que quieras instalarlo con todas las dependencias y
|
||||||
<div class="termy">
|
<div class="termy">
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ pip install fastapi[all]
|
$ pip install "fastapi[all]"
|
||||||
|
|
||||||
---> 100%
|
---> 100%
|
||||||
```
|
```
|
||||||
|
|
@ -62,7 +62,7 @@ $ pip install fastapi[all]
|
||||||
También debes instalar `uvicorn` para que funcione como tu servidor:
|
También debes instalar `uvicorn` para que funcione como tu servidor:
|
||||||
|
|
||||||
```
|
```
|
||||||
pip install uvicorn[standard]
|
pip install "uvicorn[standard]"
|
||||||
```
|
```
|
||||||
|
|
||||||
Y lo mismo para cada una de las dependencias opcionales que quieras utilizar.
|
Y lo mismo para cada una de las dependencias opcionales que quieras utilizar.
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ En este caso el parámetro de la función `q` será opcional y será `None` por
|
||||||
!!! note "Nota"
|
!!! note "Nota"
|
||||||
FastAPI sabrá que `q` es opcional por el `= None`.
|
FastAPI sabrá que `q` es opcional por el `= None`.
|
||||||
|
|
||||||
El `Optional` en `Optional[str]` no es usado por FastAPI (FastAPI solo usará la parte `str`), pero el `Optional[str]` le permitirá a tu editor ayudarte a encontrar errores en tu código.
|
El `Union` en `Union[str, None]` no es usado por FastAPI (FastAPI solo usará la parte `str`), pero el `Union[str, None]` le permitirá a tu editor ayudarte a encontrar errores en tu código.
|
||||||
|
|
||||||
## Conversión de tipos de parámetros de query
|
## Conversión de tipos de parámetros de query
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,15 @@ theme:
|
||||||
name: material
|
name: material
|
||||||
custom_dir: overrides
|
custom_dir: overrides
|
||||||
palette:
|
palette:
|
||||||
- scheme: default
|
- media: '(prefers-color-scheme: light)'
|
||||||
|
scheme: default
|
||||||
primary: teal
|
primary: teal
|
||||||
accent: amber
|
accent: amber
|
||||||
toggle:
|
toggle:
|
||||||
icon: material/lightbulb
|
icon: material/lightbulb
|
||||||
name: Switch to light mode
|
name: Switch to light mode
|
||||||
- scheme: slate
|
- media: '(prefers-color-scheme: dark)'
|
||||||
|
scheme: slate
|
||||||
primary: teal
|
primary: teal
|
||||||
accent: amber
|
accent: amber
|
||||||
toggle:
|
toggle:
|
||||||
|
|
@ -42,6 +44,7 @@ nav:
|
||||||
- es: /es/
|
- es: /es/
|
||||||
- fa: /fa/
|
- fa: /fa/
|
||||||
- fr: /fr/
|
- fr: /fr/
|
||||||
|
- he: /he/
|
||||||
- id: /id/
|
- id: /id/
|
||||||
- it: /it/
|
- it: /it/
|
||||||
- ja: /ja/
|
- ja: /ja/
|
||||||
|
|
@ -51,6 +54,7 @@ nav:
|
||||||
- pt: /pt/
|
- pt: /pt/
|
||||||
- ru: /ru/
|
- ru: /ru/
|
||||||
- sq: /sq/
|
- sq: /sq/
|
||||||
|
- sv: /sv/
|
||||||
- tr: /tr/
|
- tr: /tr/
|
||||||
- uk: /uk/
|
- uk: /uk/
|
||||||
- zh: /zh/
|
- zh: /zh/
|
||||||
|
|
@ -81,6 +85,8 @@ markdown_extensions:
|
||||||
format: !!python/name:pymdownx.superfences.fence_code_format ''
|
format: !!python/name:pymdownx.superfences.fence_code_format ''
|
||||||
- pymdownx.tabbed:
|
- pymdownx.tabbed:
|
||||||
alternate_style: true
|
alternate_style: true
|
||||||
|
- attr_list
|
||||||
|
- md_in_html
|
||||||
extra:
|
extra:
|
||||||
analytics:
|
analytics:
|
||||||
provider: google
|
provider: google
|
||||||
|
|
@ -113,6 +119,8 @@ extra:
|
||||||
name: fa
|
name: fa
|
||||||
- link: /fr/
|
- link: /fr/
|
||||||
name: fr - français
|
name: fr - français
|
||||||
|
- link: /he/
|
||||||
|
name: he
|
||||||
- link: /id/
|
- link: /id/
|
||||||
name: id
|
name: id
|
||||||
- link: /it/
|
- link: /it/
|
||||||
|
|
@ -131,6 +139,8 @@ extra:
|
||||||
name: ru - русский язык
|
name: ru - русский язык
|
||||||
- link: /sq/
|
- link: /sq/
|
||||||
name: sq - shqip
|
name: sq - shqip
|
||||||
|
- link: /sv/
|
||||||
|
name: sv - svenska
|
||||||
- link: /tr/
|
- link: /tr/
|
||||||
name: tr - Türkçe
|
name: tr - Türkçe
|
||||||
- link: /uk/
|
- link: /uk/
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,12 @@
|
||||||
|
|
||||||
{!../../../docs/missing-translation.md!}
|
|
||||||
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
|
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<em>FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
|
<em>فریمورک FastAPI، کارایی بالا، یادگیری آسان، کدنویسی سریع، آماده برای استفاده در محیط پروداکشن</em>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
|
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest" target="_blank">
|
||||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg?event=push&branch=master" alt="Test">
|
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg" alt="Test">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
|
<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">
|
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage">
|
||||||
|
|
@ -25,103 +21,99 @@
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**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 یک وب فریمورک مدرن و سریع (با کارایی بالا) برای ایجاد APIهای متنوع (وب، وبسوکت و غبره) با زبان پایتون نسخه +۳.۶ است. این فریمورک با رعایت کامل راهنمای نوع داده (Type Hint) ایجاد شده است.
|
||||||
|
|
||||||
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:
|
* **<abbr title="Fast">سرعت</abbr>**: کارایی بسیار بالا و قابل مقایسه با **NodeJS** و **Go** (با تشکر از Starlette و Pydantic). [یکی از سریعترین فریمورکهای پایتونی موجود](#performance).
|
||||||
|
|
||||||
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance).
|
* **<abbr title="Fast to code">کدنویسی سریع</abbr>**: افزایش ۲۰۰ تا ۳۰۰ درصدی سرعت توسعه فابلیتهای جدید. *
|
||||||
|
* **<abbr title="Fewer bugs">باگ کمتر</abbr>**: کاهش ۴۰ درصدی خطاهای انسانی (برنامهنویسی). *
|
||||||
|
* **<abbr title="Intuitive">غریزی</abbr>**: پشتیبانی فوقالعاده در محیطهای توسعه یکپارچه (IDE). <abbr title="یا اتوکامپلیت، اتوکامپلشن، اینتلیسنس">تکمیل</abbr> در همه بخشهای کد. کاهش زمان رفع باگ.
|
||||||
|
* **<abbr title="Easy">آسان</abbr>**: طراحی شده برای یادگیری و استفاده آسان. کاهش زمان مورد نیاز برای مراجعه به مستندات.
|
||||||
|
* **<abbr title="Short">کوچک</abbr>**: کاهش تکرار در کد. چندین قابلیت برای هر پارامتر (منظور پارامترهای ورودی تابع هندلر میباشد، به بخش <a href="https://fastapi.tiangolo.com/#recap">خلاصه</a> در همین صفحه مراجعه شود). باگ کمتر.
|
||||||
|
* **<abbr title="Robust">استوار</abbr>**: ایجاد کدی آماده برای استفاده در محیط پروداکشن و تولید خودکار <abbr title="Interactive documentation">مستندات تعاملی</abbr>
|
||||||
|
* **<abbr title="Standards-based">مبتنی بر استانداردها</abbr>**: مبتنی بر (و منطبق با) استانداردهای متن باز مربوط به API: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (سوگر سابق) و <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%. *
|
<small>* تخمینها بر اساس تستهای انجام شده در یک تیم توسعه داخلی که مشغول ایجاد برنامههای کاربردی واقعی بودند صورت گرفته است.</small>
|
||||||
* **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 -->
|
<!-- sponsors -->
|
||||||
|
|
||||||
{% if sponsors %}
|
{% if sponsors %}
|
||||||
{% for sponsor in sponsors.gold -%}
|
{% for sponsor in sponsors.gold -%}
|
||||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
|
||||||
{% endfor -%}
|
|
||||||
{%- for sponsor in sponsors.silver -%}
|
|
||||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- /sponsors -->
|
<!-- /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
|
## نظر دیگران در مورد FastAPI
|
||||||
|
|
||||||
"_[...] 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: left; direction: ltr;"><em> [...] I'm using <strong>FastAPI</strong> a ton these days. [...] I'm actually planning to use it for all of my team's <strong>ML services at Microsoft</strong>. Some of them are getting integrated into the core <strong>Windows</strong> product and some <strong>Office</strong> products."</em></div>
|
||||||
|
|
||||||
<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>
|
<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: left; direction: ltr;"><em>"We adopted the <strong>FastAPI</strong> library to spawn a <strong>REST</strong>server that can be queried to obtain <strong>predictions</strong>. [for Ludwig]"</em></div>
|
||||||
|
|
||||||
<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>
|
<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: left; direction: ltr;">"<strong>Netflix</strong> is pleased to announce the open-source release of our <strong>crisis management</strong> orchestration framework: <strong>Dispatch</strong>! [built with <strong>FastAPI</strong>]"</div>
|
||||||
|
|
||||||
<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>
|
<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: left; direction: ltr;">"<em>I’m over the moon excited about <strong>FastAPI</strong>. It’s so fun!"</em></div>
|
||||||
|
|
||||||
<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>
|
<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: left; direction: ltr;">"<em>Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted <strong>Hug</strong> to be - it's really inspiring to see someone build that."</em></div>
|
||||||
|
|
||||||
<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>
|
<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 [...]_"
|
<div style="text-align: left; direction: ltr;">"<em>If you're looking to learn one <strong>modern framework</strong> for building REST APIs, check out <strong>FastAPI</strong> [...] It's fast, easy to use and easy to learn [...]"</em></div>
|
||||||
|
|
||||||
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
|
<div style="text-align: left; direction: ltr;">"<em>We've switched over to <strong>FastAPI</strong> for our <strong>APIs</strong> [...] I think you'll like it [...]</em>"</div>
|
||||||
|
|
||||||
<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>
|
<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 برای کار با <abbr title="CLI (Command Line Interface)">واسط خط فرمان</abbr>
|
||||||
|
|
||||||
<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>
|
<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="Command Line Interface">CLI</abbr> (به جای استفاده در وب) هستید، میتوانید از <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 در برنامههای CLI باشد.️ 🚀
|
||||||
|
|
||||||
## Requirements
|
## نیازمندیها
|
||||||
|
|
||||||
Python 3.6+
|
پایتون +۳.۶
|
||||||
|
|
||||||
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://www.starlette.io/" class="external-link" target="_blank">Starlette</a> برای بخش وب.
|
||||||
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> for the data parts.
|
* کتابخانه <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> برای بخش داده.
|
||||||
|
|
||||||
## Installation
|
## نصب
|
||||||
|
|
||||||
<div class="termy">
|
<div class="termy">
|
||||||
|
|
||||||
|
|
@ -133,7 +125,7 @@ $ pip install fastapi
|
||||||
|
|
||||||
</div>
|
</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>.
|
نصب یک سرور پروداکشن نظیر <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">
|
<div class="termy">
|
||||||
|
|
||||||
|
|
@ -145,11 +137,10 @@ $ pip install "uvicorn[standard]"
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## Example
|
## مثال
|
||||||
|
|
||||||
### Create it
|
### ایجاد کنید
|
||||||
|
* فایلی به نام `main.py` با محتوای زیر ایجاد کنید :
|
||||||
* Create a file `main.py` with:
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
@ -165,14 +156,14 @@ def read_root():
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
def read_item(item_id: int, q: Optional[str] = None):
|
def read_item(item_id: int, q: Union[str, None] = None):
|
||||||
return {"item_id": item_id, "q": q}
|
return {"item_id": item_id, "q": q}
|
||||||
```
|
```
|
||||||
|
|
||||||
<details markdown="1">
|
<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"
|
```Python hl_lines="9 14"
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
@ -192,15 +183,16 @@ async def read_item(item_id: int, q: Optional[str] = None):
|
||||||
return {"item_id": item_id, "q": q}
|
return {"item_id": item_id, "q": q}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**:
|
**توجه**:
|
||||||
|
|
||||||
|
اگر با `async / await` آشنا نیستید، به بخش _"عجله دارید?"_ در صفحه درباره <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` و `await` در مستندات</a> مراجعه کنید.
|
||||||
|
|
||||||
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>
|
</details>
|
||||||
|
|
||||||
### Run it
|
### اجرا کنید
|
||||||
|
|
||||||
Run the server with:
|
با استفاده از دستور زیر سرور را اجرا کنید:
|
||||||
|
|
||||||
<div class="termy">
|
<div class="termy">
|
||||||
|
|
||||||
|
|
@ -217,54 +209,54 @@ INFO: Application startup complete.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<details markdown="1">
|
<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").
|
* `main`: فایل `main.py` (ماژول پایتون ایجاد شده).
|
||||||
* `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
|
* `app`: شیء ایجاد شده در فایل `main.py` در خط `app = FastAPI()`.
|
||||||
* `--reload`: make the server restart after code changes. Only do this for development.
|
* `--reload`: ریستارت کردن سرور با تغییر کد. تنها در هنگام توسعه از این گزینه استفاده شود..
|
||||||
|
|
||||||
</details>
|
</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
|
```JSON
|
||||||
{"item_id": 5, "q": "somequery"}
|
{"item_id": 5, "q": "somequery"}
|
||||||
```
|
```
|
||||||
|
|
||||||
You already created an API that:
|
تا اینجا شما APIای ساختید که:
|
||||||
|
|
||||||
* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`.
|
* درخواستهای HTTP به _مسیرهای_ `/` و `/items/{item_id}` را دریافت میکند.
|
||||||
* Both _paths_ take `GET` <em>operations</em> (also known as HTTP _methods_).
|
* هردو _مسیر_ <abbr title="operations در OpenAPI">عملیات</abbr> (یا HTTP _متد_) `GET` را پشتیبانی میکنند.
|
||||||
* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`.
|
* _مسیر_ `/items/{item_id}` شامل <abbr title="Path Parameter">_پارامتر مسیر_</abbr> `item_id` از نوع `int` است.
|
||||||
* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`.
|
* _مسیر_ `/items/{item_id}` شامل <abbr title="Query Parameter">_پارامتر پرسمان_</abbr> اختیاری `q` از نوع `str` است.
|
||||||
|
|
||||||
### 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` را مطابق زیر ویرایش کنید تا بتوانید <abbr title="Body">بدنه</abbr> یک درخواست `PUT` را دریافت کنید.
|
||||||
|
|
||||||
Declare the body using standard Python types, thanks to Pydantic.
|
به کمک Pydantic بدنه درخواست را با <abbr title="Type">انواع</abbr> استاندارد پایتون تعریف کنید.
|
||||||
|
|
||||||
```Python hl_lines="4 9-12 25-27"
|
```Python hl_lines="4 9-12 25-27"
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
@ -278,7 +270,7 @@ app = FastAPI()
|
||||||
class Item(BaseModel):
|
class Item(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
price: float
|
price: float
|
||||||
is_offer: Optional[bool] = None
|
is_offer: Union[bool, None] = None
|
||||||
|
|
||||||
|
|
||||||
@app.get("/")
|
@app.get("/")
|
||||||
|
|
@ -287,7 +279,7 @@ def read_root():
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/{item_id}")
|
@app.get("/items/{item_id}")
|
||||||
def read_item(item_id: int, q: Optional[str] = None):
|
def read_item(item_id: int, q: Union[str, None] = None):
|
||||||
return {"item_id": item_id, "q": q}
|
return {"item_id": item_id, "q": q}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -296,173 +288,175 @@ def update_item(item_id: int, item: Item):
|
||||||
return {"item_name": item.name, "item_id": item_id}
|
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.
|
این کار را با استفاده از انواع استاندارد و مدرن موجود در پایتون انجام میدهید.
|
||||||
|
|
||||||
You don't have to learn a new syntax, the methods or classes of a specific library, etc.
|
نیازی به یادگیری <abbr title="Syntax">نحو</abbr> جدید یا متدها و کلاسهای یک کتابخانه بخصوص و غیره نیست.
|
||||||
|
|
||||||
Just standard **Python 3.6+**.
|
تنها **پایتون +۳.۶**.
|
||||||
|
|
||||||
For example, for an `int`:
|
به عنوان مثال برای یک پارامتر از نوع `int`:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
item_id: int
|
item_id: int
|
||||||
```
|
```
|
||||||
|
|
||||||
or for a more complex `Item` model:
|
یا برای یک مدل پیچیدهتر مثل `Item`:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
item: Item
|
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.
|
* اعتبارسنجی، حتی برای اشیاء JSON تو در تو.
|
||||||
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network to Python data and types. Reading from:
|
* <abbr title="serialization, parsing, marshalling">تبدیل</abbr> داده ورودی: که از شبکه رسیده به انواع و داده پایتونی. این داده شامل:
|
||||||
* JSON.
|
* JSON.
|
||||||
* Path parameters.
|
* <abbr title="Path parameters">پارامترهای مسیر</abbr>.
|
||||||
* Query parameters.
|
* <abbr title="Query parameters">پارامترهای پرسمان</abbr>.
|
||||||
* Cookies.
|
* <abbr title="Cookies">کوکیها</abbr>.
|
||||||
* Headers.
|
* <abbr title="Headers">سرآیندها (هدرها)</abbr>.
|
||||||
* Forms.
|
* <abbr title="Forms">فرمها</abbr>.
|
||||||
* Files.
|
* <abbr title="Files">فایلها</abbr>.
|
||||||
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of output data: converting from Python data and types to network data (as JSON):
|
* <abbr title="serialization, parsing, marshalling">تبدیل</abbr> داده خروجی: تبدیل از انواع و داده پایتون به داده شبکه (مانند JSON):
|
||||||
* Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc).
|
* تبدیل انواع داده پایتونی (`str`, `int`, `float`, `bool`, `list` و غیره).
|
||||||
* `datetime` objects.
|
* اشیاء `datetime`.
|
||||||
* `UUID` objects.
|
* اشیاء `UUID`.
|
||||||
* Database models.
|
* qمدلهای پایگاهداده.
|
||||||
* ...and many more.
|
* و موارد بیشمار دیگر.
|
||||||
* Automatic interactive API documentation, including 2 alternative user interfaces:
|
* دو مدل مستند API تعاملی خودکار :
|
||||||
* Swagger UI.
|
* Swagger UI.
|
||||||
* ReDoc.
|
* 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.
|
* اعتبارسنجی اینکه پارامتر `item_id` در مسیر درخواستهای `GET` و `PUT` موجود است .
|
||||||
* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests.
|
* اعتبارسنجی اینکه پارامتر `item_id` در درخواستهای `GET` و `PUT` از نوع `int` است.
|
||||||
* 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.
|
* بررسی وجود پارامتر پرسمان اختیاری `q` (مانند `http://127.0.0.1:8000/items/foo?q=somequery`) در درخواستهای `GET`.
|
||||||
* As the `q` parameter is declared with `= None`, it is optional.
|
* از آنجا که پارامتر `q` با `= None` مقداردهی شده است, این پارامتر اختیاری است.
|
||||||
* Without the `None` it would be required (as is the body in the case with `PUT`).
|
* اگر از مقدار اولیه `None` استفاده نکنیم، این پارامتر الزامی خواهد بود (همانند بدنه درخواست در درخواست `PUT`).
|
||||||
* For `PUT` requests to `/items/{item_id}`, Read the body as JSON:
|
* برای درخواستهای `PUT` به آدرس `/items/{item_id}`, بدنه درخواست باید از نوع JSON تعریف شده باشد:
|
||||||
* Check that it has a required attribute `name` that should be a `str`.
|
* بررسی اینکه بدنه شامل فیلدی با نام `name` و از نوع `str` است.
|
||||||
* Check that it has a required attribute `price` that has to be a `float`.
|
* بررسی اینکه بدنه شامل فیلدی با نام `price` و از نوع `float` است.
|
||||||
* Check that it has an optional attribute `is_offer`, that should be a `bool`, if present.
|
* بررسی اینکه بدنه شامل فیلدی اختیاری با نام `is_offer` است, که در صورت وجود باید از نوع `bool` باشد.
|
||||||
* All this would also work for deeply nested JSON objects.
|
* تمامی این موارد برای اشیاء JSON در هر عمقی قابل بررسی میباشد.
|
||||||
* Convert from and to JSON automatically.
|
* تبدیل از/به JSON به صورت خودکار.
|
||||||
* Document everything with OpenAPI, that can be used by:
|
* مستندسازی همه چیز با استفاده از OpenAPI, که میتوان از آن برای موارد زیر استفاده کرد:
|
||||||
* 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.
|
موارد ذکر شده تنها پارهای از ویژگیهای بیشمار FastAPI است اما ایدهای کلی از طرز کار آن در اختیار قرار میدهد.
|
||||||
|
|
||||||
Try changing the line with:
|
خط زیر را به این صورت تغییر دهید:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
return {"item_name": item.name, "item_id": item_id}
|
return {"item_name": item.name, "item_id": item_id}
|
||||||
```
|
```
|
||||||
|
|
||||||
...from:
|
از:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
... "item_name": item.name ...
|
... "item_name": item.name ...
|
||||||
```
|
```
|
||||||
|
|
||||||
...to:
|
به:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
... "item_price": item.price ...
|
... "item_price": item.price ...
|
||||||
```
|
```
|
||||||
|
|
||||||
...and see how your editor will auto-complete the attributes and know their types:
|
در حین تایپ کردن توجه کنید که چگونه ویرایشگر، ویژگیهای کلاس `Item` را تشخیص داده و به تکمیل خودکار آنها کمک میکند:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
|
برای مشاهده مثالهای کاملتر که شامل قابلیتهای بیشتری از FastAPI باشد به بخش <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`.
|
* چگونگی تنظیم **<abbr title="Validation Constraints">محدودیتهای اعتبارسنجی</abbr>** به عنوان مثال `maximum_length` یا `regex`.
|
||||||
* A very powerful and easy to use **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
|
* سیستم **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** قوی و کاربردی.
|
||||||
* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth.
|
* امنیت و تایید هویت, شامل پشتیبانی از **OAuth2** مبتنی بر **JWT tokens** و **HTTP Basic**.
|
||||||
* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic).
|
* تکنیک پیشرفته برای تعریف **مدلهای چند سطحی JSON** (بر اساس Pydantic).
|
||||||
* **GraphQL** integration with <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> and other libraries.
|
* قابلیتهای اضافی دیگر (بر اساس Starlette) شامل:
|
||||||
* Many extra features (thanks to Starlette) as:
|
* **<abbr title="WebSocket">وبسوکت</abbr>**
|
||||||
* **WebSockets**
|
* **GraphQL**
|
||||||
* extremely easy tests based on `requests` and `pytest`
|
* تستهای خودکار آسان مبتنی بر `requests` و `pytest`
|
||||||
* **CORS**
|
* **CORS**
|
||||||
* **Cookie Sessions**
|
* **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). (*)
|
معیار (بنچمارک)های مستقل 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">یکی از سریعترین فریمورکهای مبتنی بر پایتون</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/esnme/ultrajson" target="_blank"><code>ujson</code></a> - برای <abbr title="تبدیل دادههای موجود در درخواستهای HTTP به داده پایتونی">"تجزیه (parse)"</abbr> سریعتر JSON .
|
||||||
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - for email validation.
|
* <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://requests.readthedocs.io" target="_blank"><code>requests</code></a> - در صورتی که میخواهید از `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://github.com/Tinche/aiofiles" target="_blank"><code>aiofiles</code></a> - در صورتی که میخواهید از `FileResponse` و `StaticFiles` استفاده کنید.
|
||||||
* <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://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - در صورتی که بخواهید از پیکربندی پیشفرض برای قالبها استفاده کنید.
|
||||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Required for `SessionMiddleware` support.
|
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - در صورتی که بخواهید با استفاده از `request.form()` از قابلیت <abbr title="تبدیل رشته متنی موجود در درخواست HTTP به انواع داده پایتون">"تجزیه (parse)"</abbr> فرم استفاده کنید.
|
||||||
* <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://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - در صورتی که بخواید از `SessionMiddleware` پشتیبانی کنید.
|
||||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
|
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - برای پشتیبانی `SchemaGenerator` در Starlet (به احتمال زیاد برای کار کردن با FastAPI به آن نیازی پیدا نمیکنید.).
|
||||||
|
* <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - در صورتی که از `GraphQLApp` پشتیبانی میکنید.
|
||||||
|
* <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://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - برای سرور اجرا کننده برنامه وب.
|
||||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
|
* <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 است.
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,15 @@ theme:
|
||||||
name: material
|
name: material
|
||||||
custom_dir: overrides
|
custom_dir: overrides
|
||||||
palette:
|
palette:
|
||||||
- scheme: default
|
- media: '(prefers-color-scheme: light)'
|
||||||
|
scheme: default
|
||||||
primary: teal
|
primary: teal
|
||||||
accent: amber
|
accent: amber
|
||||||
toggle:
|
toggle:
|
||||||
icon: material/lightbulb
|
icon: material/lightbulb
|
||||||
name: Switch to light mode
|
name: Switch to light mode
|
||||||
- scheme: slate
|
- media: '(prefers-color-scheme: dark)'
|
||||||
|
scheme: slate
|
||||||
primary: teal
|
primary: teal
|
||||||
accent: amber
|
accent: amber
|
||||||
toggle:
|
toggle:
|
||||||
|
|
@ -42,6 +44,7 @@ nav:
|
||||||
- es: /es/
|
- es: /es/
|
||||||
- fa: /fa/
|
- fa: /fa/
|
||||||
- fr: /fr/
|
- fr: /fr/
|
||||||
|
- he: /he/
|
||||||
- id: /id/
|
- id: /id/
|
||||||
- it: /it/
|
- it: /it/
|
||||||
- ja: /ja/
|
- ja: /ja/
|
||||||
|
|
@ -51,6 +54,7 @@ nav:
|
||||||
- pt: /pt/
|
- pt: /pt/
|
||||||
- ru: /ru/
|
- ru: /ru/
|
||||||
- sq: /sq/
|
- sq: /sq/
|
||||||
|
- sv: /sv/
|
||||||
- tr: /tr/
|
- tr: /tr/
|
||||||
- uk: /uk/
|
- uk: /uk/
|
||||||
- zh: /zh/
|
- zh: /zh/
|
||||||
|
|
@ -71,6 +75,8 @@ markdown_extensions:
|
||||||
format: !!python/name:pymdownx.superfences.fence_code_format ''
|
format: !!python/name:pymdownx.superfences.fence_code_format ''
|
||||||
- pymdownx.tabbed:
|
- pymdownx.tabbed:
|
||||||
alternate_style: true
|
alternate_style: true
|
||||||
|
- attr_list
|
||||||
|
- md_in_html
|
||||||
extra:
|
extra:
|
||||||
analytics:
|
analytics:
|
||||||
provider: google
|
provider: google
|
||||||
|
|
@ -103,6 +109,8 @@ extra:
|
||||||
name: fa
|
name: fa
|
||||||
- link: /fr/
|
- link: /fr/
|
||||||
name: fr - français
|
name: fr - français
|
||||||
|
- link: /he/
|
||||||
|
name: he
|
||||||
- link: /id/
|
- link: /id/
|
||||||
name: id
|
name: id
|
||||||
- link: /it/
|
- link: /it/
|
||||||
|
|
@ -121,6 +129,8 @@ extra:
|
||||||
name: ru - русский язык
|
name: ru - русский язык
|
||||||
- link: /sq/
|
- link: /sq/
|
||||||
name: sq - shqip
|
name: sq - shqip
|
||||||
|
- link: /sv/
|
||||||
|
name: sv - svenska
|
||||||
- link: /tr/
|
- link: /tr/
|
||||||
name: tr - Türkçe
|
name: tr - Türkçe
|
||||||
- link: /uk/
|
- link: /uk/
|
||||||
|
|
|
||||||
|
|
@ -205,10 +205,6 @@ Cette "attente" 🕙 se mesure en microsecondes, mais tout de même, en cumulé
|
||||||
|
|
||||||
C'est pourquoi il est logique d'utiliser du code asynchrone ⏸🔀⏯ pour des APIs web.
|
C'est pourquoi il est logique d'utiliser du code asynchrone ⏸🔀⏯ pour des APIs web.
|
||||||
|
|
||||||
La plupart des frameworks Python existants (y compris Flask et Django) ont été créés avant que les nouvelles fonctionnalités asynchrones de Python n'existent. Donc, les façons dont ils peuvent être déployés supportent l'exécution parallèle et une ancienne forme d'exécution asynchrone qui n'est pas aussi puissante que les nouvelles fonctionnalités de Python.
|
|
||||||
|
|
||||||
Et cela, bien que les spécifications principales du web asynchrone en Python (ou ASGI) ont été développées chez Django, pour ajouter le support des WebSockets.
|
|
||||||
|
|
||||||
Ce type d'asynchronicité est ce qui a rendu NodeJS populaire (bien que NodeJS ne soit pas parallèle) et c'est la force du Go en tant que langage de programmation.
|
Ce type d'asynchronicité est ce qui a rendu NodeJS populaire (bien que NodeJS ne soit pas parallèle) et c'est la force du Go en tant que langage de programmation.
|
||||||
|
|
||||||
Et c'est le même niveau de performance que celui obtenu avec **FastAPI**.
|
Et c'est le même niveau de performance que celui obtenu avec **FastAPI**.
|
||||||
|
|
|
||||||
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.
|
||||||