Compare commits

...

64 Commits

Author SHA1 Message Date
Sebastián Ramírez
1876ebc779 🔖 Release version 0.78.0 2022-05-14 14:58:04 -05:00
Sebastián Ramírez
1673b3ec11 📝 Update release notes 2022-05-14 14:53:50 -05:00
github-actions
1711403732 📝 Update release notes 2022-05-14 19:09:00 +00:00
Sebastián Ramírez
acab64b3c3 Add tests for required nonable parameters and body fields (#4907) 2022-05-14 19:08:31 +00:00
github-actions
0a8d6871fb 📝 Update release notes 2022-05-14 12:00:32 +00:00
Sebastián Ramírez
ca437cdfab 📝 Add docs recommending Union over Optional and migrate source examples (#4908)
* 📝 Add docs recommending Union over Optional

* 📝 Update docs recommending Union over Optional

* 📝 Update source examples for docs, recommend Union over Optional

* 📝 Update highlighted lines with updated source examples

* 📝 Update highlighted lines in Markdown with recent code changes

* 📝 Update docs, use Union instead of Optional

* ♻️ Update source examples to recommend Union over Optional

* 🎨 Update highlighted code in Markdown after moving from Optional to Union
2022-05-14 06:59:59 -05:00
github-actions
c5be1b0550 📝 Update release notes 2022-05-13 23:39:00 +00:00
Sebastián Ramírez
9262fa8362 Add support for not needing ... as default value in required Query(), Path(), Header(), etc. (#4906)
*  Do not require default value in Query(), Path(), Header(), etc

* 📝 Update source examples for docs with default and required values

*  Update tests with new default values and not required Ellipsis

* 📝 Update docs for Query params and update info about default value, required, Ellipsis
2022-05-13 18:38:22 -05:00
github-actions
31690dda2c 📝 Update release notes 2022-05-12 20:48:12 +00:00
Sebastián Ramírez
8b66b9ca3e 🎨 Fix default value as set in tutorial for Path Operations Advanced Configurations (#4899) 2022-05-12 20:47:31 +00:00
github-actions
975d859ac4 📝 Update release notes 2022-05-12 20:39:14 +00:00
Shahriyar Rzayev
82775f7cd0 ♻ Refactor dict value extraction to minimize key lookups fastapi/utils.py (#3139)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-12 20:38:30 +00:00
github-actions
497e5a2422 📝 Update release notes 2022-05-12 18:11:39 +00:00
Sebastián Ramírez
f31ad41dda 👷 Fix installing Material for MkDocs Insiders in CI (#4897) 2022-05-12 18:10:57 +00:00
github-actions
d75c69e01f 📝 Update release notes 2022-05-12 17:15:56 +00:00
Sebastián Ramírez
f204e8010a 👷 Add pre-commit CI instead of custom GitHub Action (#4896) 2022-05-12 17:15:13 +00:00
github-actions
bcabbf8b37 📝 Update release notes 2022-05-12 16:43:22 +00:00
Sebastián Ramírez
29df6b3e83 👷 Add pre-commit GitHub Action workflow (#4895)
Co-authored-by: pre-commit <github-actions@github.com>
2022-05-12 11:42:47 -05:00
github-actions
16f1d073db 📝 Update release notes 2022-05-12 16:16:56 +00:00
Michael Adkins
199916ac8c 📝 Add documentation for redefined path operations (#4864)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-12 11:16:16 -05:00
github-actions
4bb8ac2114 📝 Update release notes 2022-05-12 00:47:36 +00:00
Sebastián Ramírez
a5eff3b78e 🔥 Remove un-used old pending tests, already covered in other places (#4891) 2022-05-12 00:46:56 +00:00
github-actions
277a53442b 📝 Update release notes 2022-05-12 00:41:39 +00:00
Sebastián Ramírez
9cae3cdb09 🔧 Add Python formatting hooks to pre-commit (#4890) 2022-05-12 00:41:06 +00:00
github-actions
f673e64eeb 📝 Update release notes 2022-05-12 00:06:56 +00:00
Sebastián Ramírez
3d0f130ff3 🔧 Add pre-commit with first config and first formatting pass (#4888)
* 🔧 Add first pre-commit config

* 🎨 Format YAML files with pre-commit

* 🎨 Format Markdown with pre-commit

* 🎨 Format SVGs, drawio, JS, HTML with pre-commit

*  Add pre-commit to dev dependencies

* ⬇️ Extend pre-commit range to support Python 3.6
2022-05-12 00:06:16 +00:00
github-actions
9cbd42b13e 📝 Update release notes 2022-05-11 22:32:26 +00:00
Maxim Martynov
8c593a9cc9 👷 Disable CI installing Material for MkDocs in forks (#4410)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-11 17:31:52 -05:00
github-actions
f3b04a6118 📝 Update release notes 2022-05-11 21:44:52 +00:00
Matthew Evans
4fcdb31947 📝 Add OpenAPI warning to "Body - Fields" docs with extra schema extensions (#4846)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-11 16:43:47 -05:00
github-actions
1bbbdb4b7f 📝 Update release notes 2022-05-11 18:54:33 +00:00
Mário Victor Ribeiro Silva
15dd12629e 📝 Add dark mode auto switch to docs based on OS preference (#4869) 2022-05-11 13:53:57 -05:00
github-actions
0f7de452dd 📝 Update release notes 2022-05-11 18:49:56 +00:00
Lorenzo Castellino
35445828c8 📝 Update docs about Swagger UI self-hosting with newer source links (#4813)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-11 18:49:16 +00:00
github-actions
ff2daa0471 📝 Update release notes 2022-05-11 17:49:06 +00:00
jbrocher
e9098abe8c 📝 Add link to external article: Building the Poll App From Django Tutorial With FastAPI And React (#4778)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-11 17:48:25 +00:00
github-actions
062107159f 📝 Update release notes 2022-05-11 17:42:56 +00:00
水上 皓登
a38b0a7fac 🌐 Fix code examples in Japanese translation for docs/ja/docs/tutorial/testing.md (#4623)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-11 12:42:13 -05:00
github-actions
643291b9ca 📝 Update release notes 2022-05-11 17:35:38 +00:00
Samuel Borges
441f75a06c 📝 Updates links for Celery documentation (#4736)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-11 12:35:04 -05:00
github-actions
688d2db5e3 📝 Update release notes 2022-05-11 17:29:37 +00:00
hitrust
99a41e7f8d ✏ Fix example code with sets in tutorial for body nested models (#3030)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-11 17:29:02 +00:00
github-actions
d71b12f323 📝 Update release notes 2022-05-11 17:05:24 +00:00
Kinuax
cb5a200a7c ✏ Fix links to Pydantic docs (#4670)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-11 17:03:41 +00:00
Sebastián Ramírez
2aaac141dd 🔖 Release version 0.77.1 2022-05-09 23:19:32 -05:00
Sebastián Ramírez
03cbdd4f74 📝 Update release notes 2022-05-09 23:18:03 -05:00
github-actions
a7e659e472 📝 Update release notes 2022-05-10 04:12:55 +00:00
Maciej Kaczkowski
350745c545 🌐 Add Polish translation for docs/pl/docs/tutorial/index.md (#4516)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-10 04:12:18 +00:00
github-actions
d0e4015034 📝 Update release notes 2022-05-10 04:08:22 +00:00
Mohammad Raisul ISlam
b1e691091d ✏ Fix typo in deployment (#4629)
Co-authored-by: raisul1234 <raisul.islam@myalice.ai>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-10 04:07:45 +00:00
github-actions
9b4e6751bb 📝 Update release notes 2022-05-10 04:06:19 +00:00
github-actions
8082b45f24 📝 Update release notes 2022-05-10 04:05:48 +00:00
Mateus José
86c459d1e8 🌐 Add Portuguese translation for docs/pt/docs/help-fastapi.md (#4583)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-10 04:05:45 +00:00
Felix Schürmeyer
2a91ee945d 📝 Add link to german article: REST-API Programmieren mittels Python und dem FastAPI Modul (#4624)
A beginner article in German to get started with the FastAPI with a small Todo API as an example.

Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-10 04:05:10 +00:00
github-actions
764703cc56 📝 Update release notes 2022-05-10 04:03:35 +00:00
Sebastián Ramírez
71ea5883cd 🔧 Add notifications in issue for Uzbek translations (#4884) 2022-05-10 04:02:55 +00:00
github-actions
cc51b251dd 📝 Update release notes 2022-05-10 03:35:53 +00:00
Kiko Ilievski
6337186ff4 ✏ Fix small typo in docs/en/docs/tutorial/security/first-steps.md (#4515)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-10 03:35:21 +00:00
github-actions
88606940f5 📝 Update release notes 2022-05-10 03:34:23 +00:00
Mukul Mantosh
98bb5480a5 📝 Add external link: PyCharm Guide to FastAPI (#4512)
Co-authored-by: Mukul Mantosh <Mukul.Mantosh@in.bosch.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-10 03:33:51 +00:00
github-actions
170123a41f 📝 Update release notes 2022-05-10 03:32:54 +00:00
Yashasvi Singh
9262a699f2 📝 Add external link to article: Building an API with FastAPI and Supabase and Deploying on Deta (#4440)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-10 03:32:21 +00:00
github-actions
9a87c6d8d2 📝 Update release notes 2022-05-10 03:23:03 +00:00
Marcelo Trylesinski
f396912043 ⬆ Upgrade Starlette from 0.19.0 to 0.19.1 (#4819)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-10 03:22:26 +00:00
374 changed files with 1749 additions and 1157 deletions

View File

@@ -8,9 +8,9 @@ body:
Thanks for your interest in FastAPI! 🚀
Please follow these instructions, fill every question, and do every step. 🙏
I'm asking this because answering questions and solving problems in GitHub issues is what consumes most of the time.
I end up not being able to add new features, fix bugs, review pull requests, etc. as fast as I wish because I have to spend too much time handling issues.
All that, on top of all the incredible help provided by a bunch of community members, the [FastAPI Experts](https://fastapi.tiangolo.com/fastapi-people/#experts), that give a lot of their time to come here and help others.
@@ -18,7 +18,7 @@ body:
That's a lot of work they are doing, but if more FastAPI users came to help others like them just a little bit more, it would be much less effort for them (and you and me 😅).
By asking questions in a structured way (following this) it will be much easier to help you.
And there's a high chance that you will find the solution along the way and you won't even have to submit it and wait for an answer. 😎
As there are too many issues with questions, I'll have to close the incomplete ones. That will allow me (and others) to focus on helping people like you that follow the whole process and help us help you. 🤓
@@ -50,7 +50,7 @@ body:
label: Commit to Help
description: |
After submitting this, I commit to one of:
* Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.
* I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.
* Implement a Pull Request for a confirmed bug.

View File

@@ -8,9 +8,9 @@ body:
Thanks for your interest in FastAPI! 🚀
Please follow these instructions, fill every question, and do every step. 🙏
I'm asking this because answering questions and solving problems in GitHub issues is what consumes most of the time.
I end up not being able to add new features, fix bugs, review pull requests, etc. as fast as I wish because I have to spend too much time handling issues.
All that, on top of all the incredible help provided by a bunch of community members, the [FastAPI Experts](https://fastapi.tiangolo.com/fastapi-people/#experts), that give a lot of their time to come here and help others.
@@ -18,7 +18,7 @@ body:
That's a lot of work they are doing, but if more FastAPI users came to help others like them just a little bit more, it would be much less effort for them (and you and me 😅).
By asking questions in a structured way (following this) it will be much easier to help you.
And there's a high chance that you will find the solution along the way and you won't even have to submit it and wait for an answer. 😎
As there are too many issues with questions, I'll have to close the incomplete ones. That will allow me (and others) to focus on helping people like you that follow the whole process and help us help you. 🤓
@@ -50,7 +50,7 @@ body:
label: Commit to Help
description: |
After submitting this, I commit to one of:
* Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.
* I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.
* Implement a Pull Request for a confirmed bug.

View File

@@ -48,9 +48,7 @@ if __name__ == "__main__":
use_pr = pr
break
if not use_pr:
logging.error(
f"No PR found for hash: {event.workflow_run.head_commit.id}"
)
logging.error(f"No PR found for hash: {event.workflow_run.head_commit.id}")
sys.exit(0)
github_headers = {
"Authorization": f"token {settings.input_token.get_secret_value()}"

View File

@@ -1,7 +1,7 @@
import logging
import random
import time
from pathlib import Path
import random
from typing import Dict, Optional
import yaml
@@ -54,7 +54,7 @@ if __name__ == "__main__":
)
if pr.state == "open":
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:
logging.info(
f"This PR seems to be a language translation and awaiting reviews: {pr.number}"

View File

@@ -14,3 +14,4 @@ de: 3716
id: 3717
az: 3994
nl: 4701
uz: 4883

View File

@@ -14,7 +14,7 @@ from pydantic import BaseModel, BaseSettings, SecretStr
github_graphql_url = "https://api.github.com/graphql"
issues_query = """
query Q($after: String) {
query Q($after: String) {
repository(name: "fastapi", owner: "tiangolo") {
issues(first: 100, after: $after) {
edges {
@@ -47,7 +47,7 @@ query Q($after: String) {
"""
prs_query = """
query Q($after: String) {
query Q($after: String) {
repository(name: "fastapi", owner: "tiangolo") {
pullRequests(first: 100, after: $after) {
edges {

View File

@@ -22,7 +22,7 @@ jobs:
id: cache
with:
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
@@ -30,7 +30,7 @@ jobs:
if: steps.cache.outputs.cache-hit != 'true'
run: python3.7 -m flit install --deps production --extras doc
- name: Install Material for MkDocs Insiders
if: github.event.pull_request.head.repo.fork == false && steps.cache.outputs.cache-hit != 'true'
if: ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false ) && steps.cache.outputs.cache-hit != 'true'
run: pip install git+https://${{ secrets.ACTIONS_TOKEN }}@github.com/squidfunk/mkdocs-material-insiders.git
- name: Build Docs
run: python3.7 ./scripts/docs.py build-all

View File

@@ -12,7 +12,7 @@ on:
description: PR number
required: true
debug_enabled:
description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
required: false
default: false

View File

@@ -6,7 +6,7 @@ on:
workflow_dispatch:
inputs:
debug_enabled:
description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
required: false
default: false

View File

@@ -3,7 +3,7 @@ on:
workflow_run:
workflows:
- Build Docs
types:
types:
- completed
jobs:

51
.pre-commit-config.yaml Normal file
View 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.2.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: v2.32.1
hooks:
- id: pyupgrade
args:
- --py3-plus
- --keep-runtime-typing
- repo: https://github.com/myint/autoflake
rev: v1.4
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.3.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

View File

@@ -151,7 +151,7 @@ $ pip install "uvicorn[standard]"
* Create a file `main.py` with:
```Python
from typing import Optional
from typing import Union
from fastapi import FastAPI
@@ -164,7 +164,7 @@ def read_root():
@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}
```
@@ -174,7 +174,7 @@ def read_item(item_id: int, q: Optional[str] = None):
If your code uses `async` / `await`, use `async def`:
```Python hl_lines="9 14"
from typing import Optional
from typing import Union
from fastapi import FastAPI
@@ -187,7 +187,7 @@ async def read_root():
@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}
```
@@ -266,7 +266,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.
```Python hl_lines="4 9-12 25-27"
from typing import Optional
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
@@ -277,7 +277,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None
is_offer: Union[bool, None] = None
@app.get("/")
@@ -286,7 +286,7 @@ def read_root():
@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}

View File

@@ -5,13 +5,15 @@ theme:
name: material
custom_dir: overrides
palette:
- scheme: default
- media: "(prefers-color-scheme: light)"
scheme: default
primary: teal
accent: amber
toggle:
icon: material/lightbulb
name: Switch to light mode
- scheme: slate
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: teal
accent: amber
toggle:

View File

@@ -27,7 +27,7 @@ Mit einer interaktiven API-Dokumentation und explorativen webbasierten Benutzers
Alles basiert auf **Python 3.6 Typ**-Deklarationen (dank Pydantic). Es muss keine neue Syntax gelernt werden, nur standardisiertes modernes Python.
Wenn Sie eine kurze, zweiminütige, Auffrischung in der Benutzung von Python Typ-Deklarationen benötigen (auch wenn Sie FastAPI nicht nutzen), schauen Sie sich diese kurze Einführung an (Englisch): Python Types{.internal-link target=_blank}.
@@ -193,7 +193,7 @@ 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**:
* Weil Datenstrukturen von Pydantic einfach nur Instanzen ihrer definierten Klassen sind, sollten Autovervollständigung, Linting, mypy und ihre Intuition einwandfrei funktionieren.
* **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**:
* 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.

View File

@@ -149,7 +149,7 @@ $ pip install uvicorn[standard]
* Create a file `main.py` with:
```Python
from typing import Optional
from typing import Union
from fastapi import FastAPI
@@ -162,7 +162,7 @@ def read_root():
@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}
```
@@ -172,7 +172,7 @@ def read_item(item_id: int, q: Optional[str] = None):
If your code uses `async` / `await`, use `async def`:
```Python hl_lines="9 14"
from typing import Optional
from typing import Union
from fastapi import FastAPI
@@ -185,7 +185,7 @@ async def read_root():
@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}
```
@@ -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.
```Python hl_lines="4 9-12 25-27"
from typing import Optional
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
@@ -275,7 +275,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None
is_offer: Union[bool, None] = None
@app.get("/")
@@ -284,7 +284,7 @@ def read_root():
@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}
@@ -321,7 +321,7 @@ And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" targe
### Recap
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
You do that with standard modern Python types.
@@ -378,7 +378,7 @@ Coming back to the previous code example, **FastAPI** will:
* 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 `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.

View File

@@ -5,13 +5,15 @@ theme:
name: material
custom_dir: overrides
palette:
- scheme: default
- media: "(prefers-color-scheme: light)"
scheme: default
primary: teal
accent: amber
toggle:
icon: material/lightbulb
name: Switch to light mode
- scheme: slate
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: teal
accent: amber
toggle:

View File

@@ -1,5 +1,9 @@
articles:
english:
- 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_link: https://github.com/silvanmelchior
link: https://blog.devgenius.io/seamless-fastapi-configuration-with-confz-90949c14ea12
@@ -32,6 +36,10 @@ articles:
author_link: https://rodrigo-arenas.medium.com/
link: https://medium.com/analytics-vidhya/serve-a-machine-learning-model-using-sklearn-fastapi-and-docker-85aabf96729b
title: "Serve a machine learning model using Sklearn, FastAPI and Docker"
- author: Yashasvi Singh
author_link: https://hashnode.com/@aUnicornDev
link: https://aunicorndev.hashnode.dev/series/supafast-api
title: "Building an API with FastAPI and Supabase and Deploying on Deta"
- author: Navule Pavan Kumar Rao
author_link: https://www.linkedin.com/in/navule/
link: https://www.tutlinks.com/deploy-fastapi-on-ubuntu-gunicorn-caddy-2/
@@ -39,7 +47,7 @@ articles:
- author: Patrick Ladon
author_link: https://dev.to/factorlive
link: https://dev.to/factorlive/python-facebook-messenger-webhook-with-fastapi-on-glitch-4n90
title: Python Facebook messenger webhook with FastAPI on Glitch
title: Python Facebook messenger webhook with FastAPI on Glitch
- author: Dom Patmore
author_link: https://twitter.com/dompatmore
link: https://dompatmore.com/blog/authenticate-your-fastapi-app-with-auth0
@@ -200,11 +208,19 @@ articles:
author_link: https://medium.com/@williamhayes
link: https://medium.com/@williamhayes/fastapi-starlette-debug-vs-prod-5f7561db3a59
title: FastAPI/Starlette debug vs prod
- author: Mukul Mantosh
author_link: https://twitter.com/MantoshMukul
link: https://www.jetbrains.com/pycharm/guide/tutorials/fastapi-aws-kubernetes/
title: Developing FastAPI Application using K8s & AWS
german:
- author: Nico Axtmann
author_link: https://twitter.com/_nicoax
link: https://blog.codecentric.de/2019/08/inbetriebnahme-eines-scikit-learn-modells-mit-onnx-und-fastapi/
title: Inbetriebnahme eines scikit-learn-Modells mit ONNX und FastAPI
- author: Felix Schürmeyer
author_link: https://hellocoding.de/autor/felix-schuermeyer/
link: https://hellocoding.de/blog/coding-language/python/fastapi
title: REST-API Programmieren mittels Python und dem FastAPI Modul
japanese:
- author: '@bee2'
author_link: https://qiita.com/bee2

View File

@@ -36,7 +36,7 @@ For example, to declare another response with a status code `404` and a Pydantic
**FastAPI** will take the Pydantic model from there, generate the `JSON Schema`, and put it in the correct place.
The correct place is:
* In the key `content`, that has as value another JSON object (`dict`) that contains:
* A key with the media type, e.g. `application/json`, that contains as value another JSON object, that contains:
* A key `schema`, that has as the value the JSON Schema from the model, here's the correct place.

View File

@@ -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:
```Python hl_lines="4 23"
```Python hl_lines="4 25"
{!../../../docs_src/additional_status_codes/tutorial001.py!}
```
@@ -22,7 +22,7 @@ To achieve that, import `JSONResponse`, and return your content there directly,
When you return a `Response` directly, like in the example above, it will be returned directly.
It won't be serialized with a model, etc.
Make sure it has the data you want it to have, and that the values are valid JSON (if you are using `JSONResponse`).
!!! note "Technical Details"

View File

@@ -132,8 +132,8 @@ You can probably right-click each link and select an option similar to `Save lin
**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@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-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.css" class="external-link" target="_blank">`swagger-ui.css`</a>
And **ReDoc** uses the file:

View File

@@ -16,11 +16,11 @@ In this section you will see how to manage authentication and authorization with
You don't necessarily need OAuth2 scopes, and you can handle authentication and authorization however you want.
But OAuth2 with scopes can be nicely integrated into your API (with OpenAPI) and your API docs.
Nevertheless, you still enforce those scopes, or any other security/authorization requirement, however you need, in your code.
In many cases, OAuth2 with scopes can be an overkill.
But if you know you need it, or you are curious, keep reading.
## OAuth2 scopes and OpenAPI
@@ -47,7 +47,7 @@ They are normally used to declare specific security permissions, for example:
In OAuth2 a "scope" is just a string that declares a specific permission required.
It doesn't matter if it has other characters like `:` or if it is a URL.
Those details are implementation specific.
For OAuth2 they are just strings.
@@ -115,7 +115,7 @@ In this case, it requires the scope `me` (it could require more than one scope).
!!! note
You don't necessarily need to add different scopes in different places.
We are doing it here to demonstrate how **FastAPI** handles scopes declared at different levels.
```Python hl_lines="4 139 166"

View File

@@ -182,7 +182,7 @@ Now let's check the file `sql_app/schemas.py`.
To avoid confusion between the Peewee *models* and the Pydantic *models*, we will have the file `models.py` with the Peewee models, and the file `schemas.py` with the Pydantic models.
These Pydantic models define more or less a "schema" (a valid data shape).
So this will help us avoiding confusion while using both.
### Create the Pydantic *models* / schemas

View File

@@ -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.
```Python hl_lines="26-27 30"
```Python hl_lines="28-29 32"
{!../../../docs_src/dependency_testing/tutorial001.py!}
```

View File

@@ -235,7 +235,7 @@ It was one of the first extremely fast Python frameworks based on `asyncio`. It
!!! check "Inspired **FastAPI** to"
Find a way to have a crazy performance.
That's why **FastAPI** is based on Starlette, as it is the fastest framework available (tested by third-party benchmarks).
### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a>
@@ -333,7 +333,7 @@ Now APIStar is a set of tools to validate OpenAPI specifications, not a web fram
Exist.
The idea of declaring multiple things (data validation, serialization and documentation) with the same Python types, that at the same time provided great editor support, was something I considered a brilliant idea.
And after searching for a long time for a similar framework and testing many different alternatives, APIStar was the best option available.
Then APIStar stopped to exist as a server and Starlette was created, and was a new better foundation for such a system. That was the final inspiration to build **FastAPI**.
@@ -391,7 +391,7 @@ That's one of the main things that **FastAPI** adds on top, all based on Python
Handle all the core web parts. Adding features on top.
The class `FastAPI` itself inherits directly from the class `Starlette`.
So, anything that you can do with Starlette, you can do it directly with **FastAPI**, as it is basically Starlette on steroids.
### <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>

View File

@@ -142,7 +142,7 @@ Successfully installed fastapi pydantic uvicorn
* Create a `main.py` file with:
```Python
from typing import Optional
from typing import Union
from fastapi import FastAPI
@@ -155,7 +155,7 @@ def read_root():
@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}
```
@@ -350,7 +350,7 @@ If your FastAPI is a single file, for example, `main.py` without an `./app` dire
Then you would just have to change the corresponding paths to copy the file inside the `Dockerfile`:
```{ .dockerfile .annotate hl_lines="10 13" }
FROM python:3.9
FROM python:3.9
WORKDIR /code

View File

@@ -38,7 +38,7 @@ You can install an ASGI compatible server with:
!!! tip
By adding the `standard`, Uvicorn will install and use some recommended extra dependencies.
That including `uvloop`, the high-performance drop-in replacement for `asyncio`, that provides the big concurrency performance boost.
=== "Hypercorn"
@@ -59,7 +59,7 @@ You can install an ASGI compatible server with:
## Run the Server Program
You can then your application the same way you have done in the tutorials, but without the `--reload` option, e.g.:
You can then run your application the same way you have done in the tutorials, but without the `--reload` option, e.g.:
=== "Uvicorn"
@@ -89,7 +89,7 @@ You can then your application the same way you have done in the tutorials, but w
Remember to remove the `--reload` option if you were using it.
The `--reload` option consumes much more resources, is more unstable, etc.
It helps a lot during **development**, but you **shouldn't** use it in **production**.
## Hypercorn with Trio

View File

@@ -190,7 +190,7 @@ 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**:
* 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**:
* 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**:
* 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.

View File

@@ -103,4 +103,4 @@
</root>
</mxGraphModel>
</diagram>
</mxfile>
</mxfile>

View File

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -274,4 +274,4 @@
</root>
</mxGraphModel>
</diagram>
</mxfile>
</mxfile>

View File

@@ -59,4 +59,4 @@
</text></switch></g><rect x="670" y="1006" width="270" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1041px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">someapp.example.com</span><br /></font></div></div></div></foreignObject><text x="805" y="1045" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">someapp.example.com
</text></switch></g><rect x="670" y="1086" width="270" height="70" fill="#f5f5f5" stroke="#666666" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1121px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">another.example.net</span><br /></font></div></div></div></foreignObject><text x="805" y="1125" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">another.example.net
</text></switch></g><rect x="670" y="1166" width="270" height="70" fill="#f5f5f5" stroke="#666666" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1201px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">onemore.example.org</span><br /></font></div></div></div></foreignObject><text x="805" y="1205" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">onemore.example.org
</text></switch></g><rect x="430" y="1141" width="220" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 1176px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">IP:</span><br /><span style="font-size: 24px">123.124.125.126</span><br /></font></div></div></div></foreignObject><text x="540" y="1180" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">IP:...</text></switch></g><path d="M 1045 891 L 1315 891 L 1335 931 L 1315 971 L 1045 971 L 1025 931 Z" fill="#d5e8d4" stroke="#82b366" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 308px; height: 1px; padding-top: 931px; margin-left: 1026px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><span style="font-family: &quot;roboto&quot; ; font-size: 24px">Decrypted request for: someapp.example.com</span></div></div></div></foreignObject><text x="1180" y="935" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Decrypted request for: someapp.example.com</text></switch></g><path d="M 990 1081 L 1010 1081 L 1010 931 L 1025 931" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>
</text></switch></g><rect x="430" y="1141" width="220" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 1176px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">IP:</span><br /><span style="font-size: 24px">123.124.125.126</span><br /></font></div></div></div></foreignObject><text x="540" y="1180" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">IP:...</text></switch></g><path d="M 1045 891 L 1315 891 L 1335 931 L 1315 971 L 1045 971 L 1025 931 Z" fill="#d5e8d4" stroke="#82b366" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 308px; height: 1px; padding-top: 931px; margin-left: 1026px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><span style="font-family: &quot;roboto&quot; ; font-size: 24px">Decrypted request for: someapp.example.com</span></div></div></div></foreignObject><text x="1180" y="935" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Decrypted request for: someapp.example.com</text></switch></g><path d="M 990 1081 L 1010 1081 L 1010 931 L 1025 931" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" pointer-events="none"/></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -75,4 +75,4 @@
</root>
</mxGraphModel>
</diagram>
</mxfile>
</mxfile>

View File

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -107,4 +107,4 @@
</root>
</mxGraphModel>
</diagram>
</mxfile>
</mxfile>

View File

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -128,4 +128,4 @@
</root>
</mxGraphModel>
</diagram>
</mxfile>
</mxfile>

View File

@@ -59,4 +59,4 @@
</text></switch></g><rect x="670" y="1006" width="270" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1041px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">someapp.example.com</span><br /></font></div></div></div></foreignObject><text x="805" y="1045" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">someapp.example.com
</text></switch></g><rect x="670" y="1086" width="270" height="70" fill="#f5f5f5" stroke="#666666" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1121px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">another.example.net</span><br /></font></div></div></div></foreignObject><text x="805" y="1125" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">another.example.net
</text></switch></g><rect x="670" y="1166" width="270" height="70" fill="#f5f5f5" stroke="#666666" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1201px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">onemore.example.org</span><br /></font></div></div></div></foreignObject><text x="805" y="1205" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">onemore.example.org
</text></switch></g><rect x="430" y="1141" width="220" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 1176px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">IP:</span><br /><span style="font-size: 24px">123.124.125.126</span><br /></font></div></div></div></foreignObject><text x="540" y="1180" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">IP:...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>
</text></switch></g><rect x="430" y="1141" width="220" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 1176px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">IP:</span><br /><span style="font-size: 24px">123.124.125.126</span><br /></font></div></div></div></foreignObject><text x="540" y="1180" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">IP:...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -149,4 +149,4 @@
</root>
</mxGraphModel>
</diagram>
</mxfile>
</mxfile>

View File

@@ -59,4 +59,4 @@
</text></switch></g><rect x="670" y="1006" width="270" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1041px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">someapp.example.com</span><br /></font></div></div></div></foreignObject><text x="805" y="1045" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">someapp.example.com
</text></switch></g><rect x="670" y="1086" width="270" height="70" fill="#f5f5f5" stroke="#666666" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1121px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">another.example.net</span><br /></font></div></div></div></foreignObject><text x="805" y="1125" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">another.example.net
</text></switch></g><rect x="670" y="1166" width="270" height="70" fill="#f5f5f5" stroke="#666666" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1201px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">onemore.example.org</span><br /></font></div></div></div></foreignObject><text x="805" y="1205" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">onemore.example.org
</text></switch></g><rect x="430" y="1141" width="220" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 1176px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">IP:</span><br /><span style="font-size: 24px">123.124.125.126</span><br /></font></div></div></div></foreignObject><text x="540" y="1180" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">IP:...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>
</text></switch></g><rect x="430" y="1141" width="220" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 1176px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">IP:</span><br /><span style="font-size: 24px">123.124.125.126</span><br /></font></div></div></div></foreignObject><text x="540" y="1180" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">IP:...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -163,4 +163,4 @@
</root>
</mxGraphModel>
</diagram>
</mxfile>
</mxfile>

View File

@@ -59,4 +59,4 @@
</text></switch></g><rect x="670" y="1006" width="270" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1041px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">someapp.example.com</span><br /></font></div></div></div></foreignObject><text x="805" y="1045" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">someapp.example.com
</text></switch></g><rect x="670" y="1086" width="270" height="70" fill="#f5f5f5" stroke="#666666" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1121px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">another.example.net</span><br /></font></div></div></div></foreignObject><text x="805" y="1125" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">another.example.net
</text></switch></g><rect x="670" y="1166" width="270" height="70" fill="#f5f5f5" stroke="#666666" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1201px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">onemore.example.org</span><br /></font></div></div></div></foreignObject><text x="805" y="1205" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">onemore.example.org
</text></switch></g><rect x="430" y="1141" width="220" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 1176px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">IP:</span><br /><span style="font-size: 24px">123.124.125.126</span><br /></font></div></div></div></foreignObject><text x="540" y="1180" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">IP:...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>
</text></switch></g><rect x="430" y="1141" width="220" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 1176px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">IP:</span><br /><span style="font-size: 24px">123.124.125.126</span><br /></font></div></div></div></foreignObject><text x="540" y="1180" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">IP:...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -180,4 +180,4 @@
</root>
</mxGraphModel>
</diagram>
</mxfile>
</mxfile>

View File

@@ -59,4 +59,4 @@
</text></switch></g><rect x="670" y="1006" width="270" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1041px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">someapp.example.com</span><br /></font></div></div></div></foreignObject><text x="805" y="1045" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">someapp.example.com
</text></switch></g><rect x="670" y="1086" width="270" height="70" fill="#f5f5f5" stroke="#666666" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1121px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">another.example.net</span><br /></font></div></div></div></foreignObject><text x="805" y="1125" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">another.example.net
</text></switch></g><rect x="670" y="1166" width="270" height="70" fill="#f5f5f5" stroke="#666666" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1201px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">onemore.example.org</span><br /></font></div></div></div></foreignObject><text x="805" y="1205" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">onemore.example.org
</text></switch></g><rect x="430" y="1141" width="220" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 1176px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">IP:</span><br /><span style="font-size: 24px">123.124.125.126</span><br /></font></div></div></div></foreignObject><text x="540" y="1180" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">IP:...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>
</text></switch></g><rect x="430" y="1141" width="220" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 1176px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">IP:</span><br /><span style="font-size: 24px">123.124.125.126</span><br /></font></div></div></div></foreignObject><text x="540" y="1180" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">IP:...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -200,4 +200,4 @@
</root>
</mxGraphModel>
</diagram>
</mxfile>
</mxfile>

View File

@@ -59,4 +59,4 @@
</text></switch></g><rect x="670" y="1006" width="270" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1041px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">someapp.example.com</span><br /></font></div></div></div></foreignObject><text x="805" y="1045" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">someapp.example.com
</text></switch></g><rect x="670" y="1086" width="270" height="70" fill="#f5f5f5" stroke="#666666" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1121px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">another.example.net</span><br /></font></div></div></div></foreignObject><text x="805" y="1125" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">another.example.net
</text></switch></g><rect x="670" y="1166" width="270" height="70" fill="#f5f5f5" stroke="#666666" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1201px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">onemore.example.org</span><br /></font></div></div></div></foreignObject><text x="805" y="1205" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">onemore.example.org
</text></switch></g><rect x="430" y="1141" width="220" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 1176px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">IP:</span><br /><span style="font-size: 24px">123.124.125.126</span><br /></font></div></div></div></foreignObject><text x="540" y="1180" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">IP:...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>
</text></switch></g><rect x="430" y="1141" width="220" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 1176px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">IP:</span><br /><span style="font-size: 24px">123.124.125.126</span><br /></font></div></div></div></foreignObject><text x="540" y="1180" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">IP:...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -214,4 +214,4 @@
</root>
</mxGraphModel>
</diagram>
</mxfile>
</mxfile>

View File

@@ -59,4 +59,4 @@
</text></switch></g><rect x="670" y="1006" width="270" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1041px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">someapp.example.com</span><br /></font></div></div></div></foreignObject><text x="805" y="1045" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">someapp.example.com
</text></switch></g><rect x="670" y="1086" width="270" height="70" fill="#f5f5f5" stroke="#666666" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1121px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">another.example.net</span><br /></font></div></div></div></foreignObject><text x="805" y="1125" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">another.example.net
</text></switch></g><rect x="670" y="1166" width="270" height="70" fill="#f5f5f5" stroke="#666666" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 268px; height: 1px; padding-top: 1201px; margin-left: 671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">onemore.example.org</span><br /></font></div></div></div></foreignObject><text x="805" y="1205" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">onemore.example.org
</text></switch></g><rect x="430" y="1141" width="220" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 1176px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">IP:</span><br /><span style="font-size: 24px">123.124.125.126</span><br /></font></div></div></div></foreignObject><text x="540" y="1180" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">IP:...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>
</text></switch></g><rect x="430" y="1141" width="220" height="70" fill="#ffffff" stroke="#000000" stroke-width="3" pointer-events="none"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 1176px; margin-left: 431px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: none; white-space: normal; word-wrap: normal; "><font face="Roboto" data-font-src="https://fonts.googleapis.com/css?family=Roboto"><span style="font-size: 24px">IP:</span><br /><span style="font-size: 24px">123.124.125.126</span><br /></font></div></div></div></foreignObject><text x="540" y="1180" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">IP:...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg>

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -40,4 +40,4 @@
</root>
</mxGraphModel>
</diagram>
</mxfile>
</mxfile>

View File

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -148,7 +148,7 @@ $ pip install "uvicorn[standard]"
* Create a file `main.py` with:
```Python
from typing import Optional
from typing import Union
from fastapi import FastAPI
@@ -161,7 +161,7 @@ def read_root():
@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}
```
@@ -171,7 +171,7 @@ def read_item(item_id: int, q: Optional[str] = None):
If your code uses `async` / `await`, use `async def`:
```Python hl_lines="9 14"
from typing import Optional
from typing import Union
from fastapi import FastAPI
@@ -184,7 +184,7 @@ async def read_root():
@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}
```
@@ -263,7 +263,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.
```Python hl_lines="4 9-12 25-27"
from typing import Optional
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
@@ -274,7 +274,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None
is_offer: Union[bool, None] = None
@app.get("/")
@@ -283,7 +283,7 @@ def read_root():
@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}

View File

@@ -72,14 +72,14 @@ class Termynal {
* Initialise the widget, get lines, clear container and start animation.
*/
init() {
/**
/**
* Calculates width and height of Termynal container.
* If container is empty and lines are dynamically loaded, defaults to browser `auto` or CSS.
*/
*/
const containerStyle = getComputedStyle(this.container);
this.container.style.width = containerStyle.width !== '0px' ?
this.container.style.width = containerStyle.width !== '0px' ?
containerStyle.width : undefined;
this.container.style.minHeight = containerStyle.height !== '0px' ?
this.container.style.minHeight = containerStyle.height !== '0px' ?
containerStyle.height : undefined;
this.container.setAttribute('data-termynal', '');
@@ -138,7 +138,7 @@ class Termynal {
restart.innerHTML = "restart ↻"
return restart
}
generateFinish() {
const finish = document.createElement('a')
finish.onclick = (e) => {
@@ -215,7 +215,7 @@ class Termynal {
/**
* Converts line data objects into line elements.
*
*
* @param {Object[]} lineData - Dynamically loaded lines.
* @param {Object} line - Line data object.
* @returns {Element[]} - Array of line elements.
@@ -231,7 +231,7 @@ class Termynal {
/**
* Helper function for generating attributes string.
*
*
* @param {Object} line - Line data object.
* @returns {string} - String of attributes.
*/

View File

@@ -29,7 +29,7 @@ Calling this program outputs:
John Doe
```
The function does the following:
The function does the following:
* Takes a `first_name` and `last_name`.
* Converts the first letter of each one to upper case with `title()`.
@@ -317,6 +317,45 @@ This also means that in Python 3.10, you can use `Something | None`:
{!> ../../../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[str, SomeType]` 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
These types that take type parameters in square brackets are called **Generic types** or **Generics**, for example:
@@ -334,14 +373,14 @@ These types that take type parameters in square brackets are called **Generic ty
=== "Python 3.9 and above"
You can use the same builtin types as generics (with square brakets and types inside):
* `list`
* `tuple`
* `set`
* `dict`
And the same as with Python 3.6, from the `typing` module:
* `Union`
* `Optional`
* ...and others.
@@ -354,7 +393,7 @@ These types that take type parameters in square brackets are called **Generic ty
* `tuple`
* `set`
* `dict`
And the same as with Python 3.6, from the `typing` module:
* `Union`
@@ -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}.
!!! 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**
**FastAPI** takes advantage of these type hints to do several things.

View File

@@ -3,6 +3,135 @@
## Latest Changes
## 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
### Upgrades
* ⬆ Upgrade Starlette from 0.19.0 to 0.19.1. PR [#4819](https://github.com/tiangolo/fastapi/pull/4819) by [@Kludex](https://github.com/Kludex).
### Docs
* 📝 Add link to german article: REST-API Programmieren mittels Python und dem FastAPI Modul. PR [#4624](https://github.com/tiangolo/fastapi/pull/4624) by [@fschuermeyer](https://github.com/fschuermeyer).
* 📝 Add external link: PyCharm Guide to FastAPI. PR [#4512](https://github.com/tiangolo/fastapi/pull/4512) by [@mukulmantosh](https://github.com/mukulmantosh).
* 📝 Add external link to article: Building an API with FastAPI and Supabase and Deploying on Deta. PR [#4440](https://github.com/tiangolo/fastapi/pull/4440) by [@aUnicornDev](https://github.com/aUnicornDev).
* ✏ Fix small typo in `docs/en/docs/tutorial/security/first-steps.md`. PR [#4515](https://github.com/tiangolo/fastapi/pull/4515) by [@KikoIlievski](https://github.com/KikoIlievski).
### Translations
* 🌐 Add Polish translation for `docs/pl/docs/tutorial/index.md`. PR [#4516](https://github.com/tiangolo/fastapi/pull/4516) by [@MKaczkow](https://github.com/MKaczkow).
* ✏ Fix typo in deployment. PR [#4629](https://github.com/tiangolo/fastapi/pull/4629) by [@raisulislam541](https://github.com/raisulislam541).
* 🌐 Add Portuguese translation for `docs/pt/docs/help-fastapi.md`. PR [#4583](https://github.com/tiangolo/fastapi/pull/4583) by [@mateusjs](https://github.com/mateusjs).
### Internal
* 🔧 Add notifications in issue for Uzbek translations. PR [#4884](https://github.com/tiangolo/fastapi/pull/4884) by [@tiangolo](https://github.com/tiangolo).
## 0.77.0
### Upgrades

View File

@@ -89,7 +89,7 @@ You can see more details in <a href="https://www.starlette.io/background/" class
## 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.

View File

@@ -334,7 +334,7 @@ from app.routers import items, users
```Python
from .routers import items, users
```
The second version is an "absolute import":
```Python

View File

@@ -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.
!!! 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
You can use Pydantic's `Field` to declare extra validations and metadata for model attributes.

View File

@@ -89,13 +89,13 @@ But you can instruct **FastAPI** to treat it as another body key using `Body`:
=== "Python 3.6 and above"
```Python hl_lines="23"
```Python hl_lines="22"
{!> ../../../docs_src/body_multiple_params/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="21"
```Python hl_lines="20"
{!> ../../../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:
```Python
q: Optional[str] = None
q: Union[str, None] = None
```
Or in Python 3.10 and above:
@@ -139,7 +139,7 @@ For example:
=== "Python 3.6 and above"
```Python hl_lines="28"
```Python hl_lines="27"
{!> ../../../docs_src/body_multiple_params/tutorial004.py!}
```
@@ -152,7 +152,6 @@ For example:
!!! info
`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
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`:
```Python
item: Item = Body(..., embed=True)
item: Item = Body(embed=True)
```
as in:

View File

@@ -366,7 +366,7 @@ In this case, you would accept any `dict` as long as it has `int` keys with `flo
But Pydantic has automatic data conversion.
This means that, even though your API clients can only send strings as keys, as long as those strings contain pure integers, Pydantic will convert them and validate them.
And the `dict` you receive as `weights` will actually have `int` keys and `float` values.
## Recap

View File

@@ -138,7 +138,7 @@ But you would get the same editor support with <a href="https://www.jetbrains.co
If you use <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> as your editor, you can use the <a href="https://github.com/koxudaxi/pydantic-pycharm-plugin/" class="external-link" target="_blank">Pydantic PyCharm Plugin</a>.
It improves editor support for Pydantic models, with:
* auto-completion
* type checks
* refactoring
@@ -206,7 +206,7 @@ The function parameters will be recognized as follows:
!!! note
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

View File

@@ -109,7 +109,7 @@ Pay attention to the `__init__` method used to create the instance of the class:
=== "Python 3.6 and above"
```Python hl_lines="8"
```Python hl_lines="9"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```

View File

@@ -10,7 +10,7 @@ To do this, use `yield` instead of `return`, and write the extra steps after.
!!! note "Technical Details"
Any function that is valid to use with:
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager" class="external-link" target="_blank">`@contextlib.contextmanager`</a> or
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager" class="external-link" target="_blank">`@contextlib.contextmanager`</a> or
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager" class="external-link" target="_blank">`@contextlib.asynccontextmanager`</a>
would be valid to use as a **FastAPI** dependency.
@@ -207,7 +207,7 @@ You can also use them inside of **FastAPI** dependencies with `yield` by using
!!! tip
Another way to create a context manager is with:
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager" class="external-link" target="_blank">`@contextlib.contextmanager`</a> or
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager" class="external-link" target="_blank">`@contextlib.contextmanager`</a> or
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager" class="external-link" target="_blank">`@contextlib.asynccontextmanager`</a>
using them to decorate a function with a single `yield`.

View File

@@ -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 hl_lines="8-9"
```Python hl_lines="8-11"
{!> ../../../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 hl_lines="13 18"
```Python hl_lines="15 20"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```

View File

@@ -55,7 +55,7 @@ Then we can use the dependency with:
=== "Python 3.6 and above"
```Python hl_lines="21"
```Python hl_lines="22"
{!> ../../../docs_src/dependencies/tutorial005.py!}
```

View File

@@ -36,7 +36,7 @@ Here are some of the additional data types you can use:
* `datetime.timedelta`:
* A Python `datetime.timedelta`.
* 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`:
* 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`.

View File

@@ -163,7 +163,7 @@ path -> item_id
!!! warning
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.

View File

@@ -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:
```Python hl_lines="8"
```Python hl_lines="7"
{!../../../docs_src/path_params_numeric_validations/tutorial002.py!}
```
@@ -71,7 +71,7 @@ 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 hl_lines="8"
```Python hl_lines="7"
{!../../../docs_src/path_params_numeric_validations/tutorial003.py!}
```

View File

@@ -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"`.
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
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>.

View File

@@ -16,12 +16,12 @@ Let's take this application as example:
{!> ../../../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
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
@@ -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!}
```
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:
```Python
q: Optional[str] = Query(None)
q: Union[str, None] = Query(default=None)
```
...makes the parameter optional, the same as:
```Python
q: Optional[str] = None
q: Union[str, None] = None
```
And in Python 3.10 and above:
```Python
q: str | None = Query(None)
q: str | None = Query(default=None)
```
...makes the parameter optional, the same as:
@@ -97,17 +97,17 @@ But it declares it explicitly as being a query parameter.
or the:
```Python
= Query(None)
= Query(default=None)
```
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:
```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*.
@@ -118,7 +118,7 @@ You can also add a parameter `min_length`:
=== "Python 3.6 and above"
```Python hl_lines="9"
```Python hl_lines="10"
{!> ../../../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 hl_lines="10"
```Python hl_lines="11"
{!> ../../../docs_src/query_params_str_validations/tutorial004.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="8"
```Python hl_lines="9"
{!> ../../../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
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"`:
@@ -178,26 +178,68 @@ q: str
instead of:
```Python
q: Optional[str] = None
q: Union[str, None] = None
```
But we are now declaring it with `Query`, for example like:
```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"
{!../../../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
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.
### 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="8"
{!> ../../../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
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 hl_lines="7"
```Python hl_lines="8"
{!> ../../../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 hl_lines="7"
```Python hl_lines="8"
{!> ../../../docs_src/query_params_str_validations/tutorial014_py310.py!}
```

View File

@@ -106,7 +106,7 @@ The way HTML forms (`<form></form>`) sends the data to the server normally uses
Data from forms is normally encoded using the "media type" `application/x-www-form-urlencoded` when it doesn't include files.
But when the form includes files, it is encoded as `multipart/form-data`. If you use `File`, **FastAPI** will know it has to get the files from the correct part of the body.
If you want to read more about these encodings and form fields, head to the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> web docs for <code>POST</code></a>.
!!! warning

View File

@@ -45,7 +45,7 @@ The way HTML forms (`<form></form>`) sends the data to the server normally uses
Data from forms is normally encoded using the "media type" `application/x-www-form-urlencoded`.
But when the form includes files, it is encoded as `multipart/form-data`. You'll read about handling files in the next chapter.
If you want to read more about these encodings and form fields, head to the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> web docs for <code>POST</code></a>.
!!! warning

View File

@@ -162,7 +162,7 @@ Your response model could have default values, like:
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
```
* `description: Optional[str] = None` has a default of `None`.
* `description: Union[str, None] = None` has a default of `None`.
* `tax: float = 10.5` has a default of `10.5`.
* `tags: List[str] = []` as a default of an empty list: `[]`.

View File

@@ -68,13 +68,13 @@ Here we pass an `example` of the data expected in `Body()`:
=== "Python 3.6 and above"
```Python hl_lines="21-26"
```Python hl_lines="20-25"
{!> ../../../docs_src/schema_extra_example/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="19-24"
```Python hl_lines="18-23"
{!> ../../../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 hl_lines="22-48"
```Python hl_lines="21-47"
{!> ../../../docs_src/schema_extra_example/tutorial004.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="20-46"
```Python hl_lines="19-45"
{!> ../../../docs_src/schema_extra_example/tutorial004_py310.py!}
```

View File

@@ -121,7 +121,7 @@ When we create an instance of the `OAuth2PasswordBearer` class we pass in the `t
```
!!! tip
here `tokenUrl="token"` refers to a relative URL `token` that we haven't created yet. As it's a relative URL, it's equivalent to `./token`.
Here `tokenUrl="token"` refers to a relative URL `token` that we haven't created yet. As it's a relative URL, it's equivalent to `./token`.
Because we are using a relative URL, if your API was located at `https://example.com/`, then it would refer to `https://example.com/token`. But if your API was located at `https://example.com/api/v1/`, then it would refer to `https://example.com/api/v1/token`.

View File

@@ -317,7 +317,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.
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`.
@@ -616,7 +616,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**.
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

View File

@@ -5,13 +5,15 @@ theme:
name: material
custom_dir: overrides
palette:
- scheme: default
- media: "(prefers-color-scheme: light)"
scheme: default
primary: teal
accent: amber
toggle:
icon: material/lightbulb
name: Switch to light mode
- scheme: slate
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: teal
accent: amber
toggle:

View File

@@ -69,9 +69,9 @@
});
});
</script>
<qa-bot
<qa-bot
server="https://tiangolo-fastapi.docsqa.jina.ai"
theme="infer"
theme="infer"
title="FastAPI Bot"
description="FastAPI framework, high performance, easy to learn, fast to code, ready for production"
style="font-size: 0.8rem"

View File

@@ -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:
```Python hl_lines="2 19"
```Python hl_lines="4 25"
{!../../../docs_src/additional_status_codes/tutorial001.py!}
```

View File

@@ -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**:
* 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**:
* 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**:
* 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.

View File

@@ -145,7 +145,7 @@ $ pip install uvicorn[standard]
```Python
from fastapi import FastAPI
from typing import Optional
from typing import Union
app = FastAPI()
@@ -156,7 +156,7 @@ def read_root():
@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}
```
@@ -167,7 +167,7 @@ Si tu código usa `async` / `await`, usa `async def`:
```Python hl_lines="7 12"
from fastapi import FastAPI
from typing import Optional
from typing import Union
app = FastAPI()
@@ -178,7 +178,7 @@ async def read_root():
@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}
```
@@ -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"
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional
from typing import Union
app = FastAPI()
@@ -267,7 +267,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None
is_offer: Union[bool, None] = None
@app.get("/")
@@ -276,7 +276,7 @@ def read_root():
@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}

View File

@@ -254,7 +254,7 @@ El `@app.get("/")` le dice a **FastAPI** que la función que tiene justo debajo
Esa sintaxis `@algo` se llama un "decorador" en Python.
Lo pones encima de una función. Es como un lindo sombrero decorado (creo que de ahí salió el concepto).
Un "decorador" toma la función que tiene debajo y hace algo con ella.
En nuestro caso, este decorador le dice a **FastAPI** que la función que está debajo corresponde al **path** `/` con una **operación** `get`.

View File

@@ -75,7 +75,7 @@ En este caso el parámetro de la función `q` será opcional y será `None` por
!!! note "Nota"
FastAPI sabrá que `q` es opcional por el `= None`.
El `Optional` en `Optional[str]` no es usado por FastAPI (FastAPI solo usará la parte `str`), pero el `Optional[str]` le permitirá a tu editor ayudarte a encontrar errores en tu código.
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

View File

@@ -5,13 +5,15 @@ theme:
name: material
custom_dir: overrides
palette:
- scheme: default
- media: "(prefers-color-scheme: light)"
scheme: default
primary: teal
accent: amber
toggle:
icon: material/lightbulb
name: Switch to light mode
- scheme: slate
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: teal
accent: amber
toggle:

View File

@@ -152,7 +152,7 @@ $ pip install "uvicorn[standard]"
* Create a file `main.py` with:
```Python
from typing import Optional
from typing import Union
from fastapi import FastAPI
@@ -165,7 +165,7 @@ def read_root():
@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}
```
@@ -175,7 +175,7 @@ def read_item(item_id: int, q: Optional[str] = None):
If your code uses `async` / `await`, use `async def`:
```Python hl_lines="9 14"
from typing import Optional
from typing import Union
from fastapi import FastAPI
@@ -188,7 +188,7 @@ async def read_root():
@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}
```
@@ -267,7 +267,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.
```Python hl_lines="4 9-12 25-27"
from typing import Optional
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
@@ -278,7 +278,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None
is_offer: Union[bool, None] = None
@app.get("/")
@@ -287,7 +287,7 @@ def read_root():
@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}

View File

@@ -5,13 +5,15 @@ theme:
name: material
custom_dir: overrides
palette:
- scheme: default
- media: "(prefers-color-scheme: light)"
scheme: default
primary: teal
accent: amber
toggle:
icon: material/lightbulb
name: Switch to light mode
- scheme: slate
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: teal
accent: amber
toggle:

View File

@@ -133,7 +133,7 @@ permanents qui les rendent inadaptés.
### <a href="https://marshmallow.readthedocs.io/en/3.0/" class="external-link" target="_blank">Marshmallow</a>
L'une des principales fonctionnalités nécessaires aux systèmes API est la "<abbr title="également appelée
L'une des principales fonctionnalités nécessaires aux systèmes API est la "<abbr title="également appelée
marshalling, conversion">sérialisation</abbr>" des données, qui consiste à prendre les données du code (Python) et à
les convertir en quelque chose qui peut être envoyé sur le réseau. Par exemple, convertir un objet contenant des
données provenant d'une base de données en un objet JSON. Convertir des objets `datetime` en strings, etc.
@@ -147,7 +147,7 @@ Sans un système de validation des données, vous devriez effectuer toutes les v
Ces fonctionnalités sont ce pourquoi Marshmallow a été construit. C'est une excellente bibliothèque, et je l'ai déjà beaucoup utilisée.
Mais elle a été créée avant que les type hints n'existent en Python. Ainsi, pour définir chaque <abbr title="la définition de
Mais elle a été créée avant que les type hints n'existent en Python. Ainsi, pour définir chaque <abbr title="la définition de
la façon dont les données doivent être formées">schéma</abbr>, vous devez utiliser des utilitaires et des classes spécifiques fournies par Marshmallow.
!!! check "A inspiré **FastAPI** à"
@@ -155,7 +155,7 @@ Utilisez du code pour définir des "schémas" qui fournissent automatiquement le
### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a>
Une autre grande fonctionnalité requise par les API est le <abbr title="la lecture et la conversion en données
Une autre grande fonctionnalité requise par les API est le <abbr title="la lecture et la conversion en données
Python">parsing</abbr> des données provenant des requêtes entrantes.
Webargs est un outil qui a été créé pour fournir cela par-dessus plusieurs frameworks, dont Flask.

View File

@@ -220,7 +220,7 @@ Et comme on peut avoir du parallélisme et de l'asynchronicité en même temps,
Nope ! C'est ça la morale de l'histoire.
La concurrence est différente du parallélisme. C'est mieux sur des scénarios **spécifiques** qui impliquent beaucoup d'attente. À cause de ça, c'est généralement bien meilleur que le parallélisme pour le développement d'applications web. Mais pas pour tout.
Donc pour équilibrer tout ça, imaginez l'histoire suivante :
> Vous devez nettoyer une grande et sale maison.
@@ -293,7 +293,7 @@ def get_sequential_burgers(number: int):
Avec `async def`, Python sait que dans cette fonction il doit prendre en compte les expressions `await`, et qu'il peut mettre en pause ⏸ l'exécution de la fonction pour aller faire autre chose 🔀 avant de revenir.
Pour appeler une fonction définie avec `async def`, vous devez utiliser `await`. Donc ceci ne marche pas :
Pour appeler une fonction définie avec `async def`, vous devez utiliser `await`. Donc ceci ne marche pas :
```Python
# Ceci ne fonctionne pas, car get_burgers a été défini avec async def
@@ -375,7 +375,7 @@ Au final, dans les deux situations, il est fort probable que **FastAPI** soit to
La même chose s'applique aux dépendances. Si une dépendance est définie avec `def` plutôt que `async def`, elle est exécutée dans la threadpool externe.
### Sous-dépendances
### Sous-dépendances
Vous pouvez avoir de multiples dépendances et sous-dépendances dépendant les unes des autres (en tant que paramètres de la définition de la *fonction de chemin*), certaines créées avec `async def` et d'autres avec `def`. Cela fonctionnerait aussi, et celles définies avec un simple `def` seraient exécutées sur un thread externe (venant de la threadpool) plutôt que d'être "attendues".

View File

@@ -118,7 +118,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage
</div>
Vous disposez maintenant d'un serveur FastAPI optimisé dans un conteneur Docker. Configuré automatiquement pour votre
Vous disposez maintenant d'un serveur FastAPI optimisé dans un conteneur Docker. Configuré automatiquement pour votre
serveur actuel (et le nombre de cœurs du CPU).
## Vérifier
@@ -139,7 +139,7 @@ Vous verrez la documentation interactive automatique de l'API (fournie par <a hr
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
## Documentation de l'API alternative
## Documentation de l'API alternative
Et vous pouvez également aller sur <a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> ou <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a> (ou équivalent, en utilisant votre hôte Docker).
@@ -149,7 +149,7 @@ Vous verrez la documentation automatique alternative (fournie par <a href="https
## Traefik
<a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a> est un reverse proxy/load balancer
<a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a> est un reverse proxy/load balancer
haute performance. Il peut faire office de "Proxy de terminaison TLS" (entre autres fonctionnalités).
Il est intégré à Let's Encrypt. Ainsi, il peut gérer toutes les parties HTTPS, y compris l'acquisition et le renouvellement des certificats.
@@ -164,7 +164,7 @@ Avec ces informations et ces outils, passez à la section suivante pour tout com
Vous pouvez avoir un cluster en mode Docker Swarm configuré en quelques minutes (environ 20 min) avec un processus Traefik principal gérant HTTPS (y compris l'acquisition et le renouvellement des certificats).
En utilisant le mode Docker Swarm, vous pouvez commencer par un "cluster" d'une seule machine (il peut même s'agir
En utilisant le mode Docker Swarm, vous pouvez commencer par un "cluster" d'une seule machine (il peut même s'agir
d'un serveur à 5 USD/mois) et ensuite vous pouvez vous développer autant que vous le souhaitez en ajoutant d'autres serveurs.
Pour configurer un cluster en mode Docker Swarm avec Traefik et la gestion de HTTPS, suivez ce guide :

View File

@@ -27,7 +27,7 @@ Documentation d'API interactive et interface web d'exploration. Comme le framewo
Tout est basé sur la déclaration de type standard de **Python 3.6** (grâce à Pydantic). Pas de nouvelles syntaxes à apprendre. Juste du Python standard et moderne.
Si vous souhaitez un rappel de 2 minutes sur l'utilisation des types en Python (même si vous ne comptez pas utiliser FastAPI), jetez un oeil au tutoriel suivant: [Python Types](python-types.md){.internal-link target=_blank}.
Si vous souhaitez un rappel de 2 minutes sur l'utilisation des types en Python (même si vous ne comptez pas utiliser FastAPI), jetez un oeil au tutoriel suivant: [Python Types](python-types.md){.internal-link target=_blank}.
Vous écrivez du python standard avec des annotations de types:
@@ -190,7 +190,7 @@ Avec **FastAPI** vous aurez toutes les fonctionnalités de **Pydantic** (comme
* Aide votre **<abbr title="Integrated Development Environment, il s'agit de votre éditeur de code">IDE</abbr>/<abbr title="Programme qui analyse le code à la recherche d'erreurs">linter</abbr>/cerveau**:
* Parce que les structures de données de pydantic consistent seulement en une instance de classe que vous définissez; l'auto-complétion, le linting, mypy et votre intuition devrait être largement suffisante pour valider vos données.
* **Rapide**:
* Dans les <a href="https://pydantic-docs.helpmanual.io/#benchmarks-tag" class="external-link" target="_blank">benchmarks</a> Pydantic est plus rapide que toutes les autres librairies testées.
* Dans les <a href="https://pydantic-docs.helpmanual.io/benchmarks/" class="external-link" target="_blank">benchmarks</a> Pydantic est plus rapide que toutes les autres librairies testées.
* Valide les **structures complexes**:
* Utilise les modèles hiérarchique de Pydantic, le `typage` Python pour les `Lists`, `Dict`, etc.
* Et les validateurs permettent aux schémas de données complexes d'être clairement et facilement définis, validés et documentés sous forme d'un schéma JSON.

View File

@@ -149,7 +149,7 @@ $ pip install uvicorn[standard]
* Create a file `main.py` with:
```Python
from typing import Optional
from typing import Union
from fastapi import FastAPI
@@ -162,7 +162,7 @@ def read_root():
@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}
```
@@ -172,7 +172,7 @@ def read_item(item_id: int, q: Optional[str] = None):
If your code uses `async` / `await`, use `async def`:
```Python hl_lines="9 14"
from typing import Optional
from typing import Union
from fastapi import FastAPI
@@ -185,7 +185,7 @@ async def read_root():
@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}
```
@@ -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.
```Python hl_lines="4 9 10 11 12 25 26 27"
from typing import Optional
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
@@ -275,7 +275,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None
is_offer: Union[bool, None] = None
@app.get("/")
@@ -284,7 +284,7 @@ def read_root():
@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}
@@ -321,7 +321,7 @@ And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" targe
### Recap
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
You do that with standard modern Python types.
@@ -378,7 +378,7 @@ Coming back to the previous code example, **FastAPI** will:
* 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 `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.
@@ -463,4 +463,4 @@ You can install all of these with `pip install fastapi[all]`.
## License
This project is licensed under the terms of the MIT license.
This project is licensed under the terms of the MIT license.

View File

@@ -9,7 +9,7 @@ Cela comprend, par exemple :
* Les notifications par email envoyées après l'exécution d'une action :
* Étant donné que se connecter à un serveur et envoyer un email a tendance à être «lent» (plusieurs secondes), vous pouvez retourner la réponse directement et envoyer la notification en arrière-plan.
* Traiter des données :
* Par exemple, si vous recevez un fichier qui doit passer par un traitement lent, vous pouvez retourner une réponse «Accepted» (HTTP 202) puis faire le traitement en arrière-plan.
* Par exemple, si vous recevez un fichier qui doit passer par un traitement lent, vous pouvez retourner une réponse «Accepted» (HTTP 202) puis faire le traitement en arrière-plan.
## Utiliser `BackgroundTasks`
@@ -73,7 +73,7 @@ La classe `BackgroundTasks` provient directement de <a href="https://www.starlet
Elle est importée/incluse directement dans **FastAPI** pour que vous puissiez l'importer depuis `fastapi` et éviter d'importer accidentellement `BackgroundTask` (sans `s` à la fin) depuis `starlette.background`.
En utilisant seulement `BackgroundTasks` (et non `BackgroundTask`), il est possible de l'utiliser en tant que paramètre de *fonction de chemin* et de laisser **FastAPI** gérer le reste pour vous, comme en utilisant l'objet `Request` directement.
En utilisant seulement `BackgroundTasks` (et non `BackgroundTask`), il est possible de l'utiliser en tant que paramètre de *fonction de chemin* et de laisser **FastAPI** gérer le reste pour vous, comme en utilisant l'objet `Request` directement.
Il est tout de même possible d'utiliser `BackgroundTask` seul dans **FastAPI**, mais dans ce cas il faut créer l'objet dans le code et renvoyer une `Response` Starlette l'incluant.
@@ -81,7 +81,7 @@ Plus de détails sont disponibles dans <a href="https://www.starlette.io/backgro
## Avertissement
Si vous avez besoin de réaliser des traitements lourds en tâche d'arrière-plan et que vous n'avez pas besoin que ces traitements aient lieu dans le même process (par exemple, pas besoin de partager la mémoire, les variables, etc.), il peut s'avérer profitable d'utiliser des outils plus importants tels que <a href="https://docs.celeryproject.org" class="external-link" target="_blank">Celery</a>.
Si vous avez besoin de réaliser des traitements lourds en tâche d'arrière-plan et que vous n'avez pas besoin que ces traitements aient lieu dans le même process (par exemple, pas besoin de partager la mémoire, les variables, etc.), il peut s'avérer profitable d'utiliser des outils plus importants tels que <a href="https://docs.celeryq.dev" class="external-link" target="_blank">Celery</a>.
Ces outils nécessitent généralement des configurations plus complexes ainsi qu'un gestionnaire de queue de message, comme RabbitMQ ou Redis, mais ils permettent d'exécuter des tâches d'arrière-plan dans différents process, et potentiellement, sur plusieurs serveurs.

View File

@@ -162,4 +162,4 @@ Les paramètres de la fonction seront reconnus comme tel :
## Sans Pydantic
Si vous ne voulez pas utiliser des modèles Pydantic, vous pouvez aussi utiliser des paramètres de **Corps**. Pour cela, allez voir la partie de la documentation sur [Corps de la requête - Paramètres multiples](body-multiple-params.md){.internal-link target=_blank}.
Si vous ne voulez pas utiliser des modèles Pydantic, vous pouvez aussi utiliser des paramètres de **Corps**. Pour cela, allez voir la partie de la documentation sur [Corps de la requête - Paramètres multiples](body-multiple-params.md){.internal-link target=_blank}.

View File

@@ -280,7 +280,7 @@ Tout comme celles les plus exotiques :
**FastAPI** n'impose pas de sens spécifique à chacune d'elle.
Les informations qui sont présentées ici forment une directive générale, pas des obligations.
Les informations qui sont présentées ici forment une directive générale, pas des obligations.
Par exemple, quand l'on utilise **GraphQL**, toutes les actions sont effectuées en utilisant uniquement des opérations `POST`.

View File

@@ -8,7 +8,7 @@ Vous pouvez déclarer des "paramètres" ou "variables" de chemin avec la même s
{!../../../docs_src/path_params/tutorial001.py!}
```
La valeur du paramètre `item_id` sera transmise à la fonction dans l'argument `item_id`.
La valeur du paramètre `item_id` sera transmise à la fonction dans l'argument `item_id`.
Donc, si vous exécutez cet exemple et allez sur <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>,
vous verrez comme réponse :
@@ -44,7 +44,7 @@ Si vous exécutez cet exemple et allez sur <a href="http://127.0.0.1:8000/items/
Comme vous l'avez remarqué, la valeur reçue par la fonction (et renvoyée ensuite) est `3`,
en tant qu'entier (`int`) Python, pas la chaîne de caractères (`string`) `"3"`.
Grâce aux déclarations de types, **FastAPI** fournit du
Grâce aux déclarations de types, **FastAPI** fournit du
<abbr title="conversion de la chaîne de caractères venant de la requête HTTP en données Python">"parsing"</abbr> automatique.
## Validation de données
@@ -91,7 +91,7 @@ documentation générée automatiquement et interactive :
On voit bien dans la documentation que `item_id` est déclaré comme entier.
## Les avantages d'avoir une documentation basée sur une norme, et la documentation alternative.
## Les avantages d'avoir une documentation basée sur une norme, et la documentation alternative.
Le schéma généré suivant la norme <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md" class="external-link" target="_blank">OpenAPI</a>,
il existe de nombreux outils compatibles.
@@ -102,7 +102,7 @@ sur <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">
<img src="/img/tutorial/path-params/image02.png">
De la même façon, il existe bien d'autres outils compatibles, y compris des outils de génération de code
pour de nombreux langages.
pour de nombreux langages.
## Pydantic

View File

@@ -6,7 +6,7 @@ Quand vous déclarez des paramètres dans votre fonction de chemin qui ne font p
{!../../../docs_src/query_params/tutorial001.py!}
```
La partie appelée requête (ou **query**) dans une URL est l'ensemble des paires clés-valeurs placées après le `?` , séparées par des `&`.
La partie appelée requête (ou **query**) dans une URL est l'ensemble des paires clés-valeurs placées après le `?` , séparées par des `&`.
Par exemple, dans l'URL :
@@ -120,7 +120,7 @@ ou n'importe quelle autre variation de casse (tout en majuscules, uniquement la
## Multiples paramètres de chemin et de requête
Vous pouvez déclarer plusieurs paramètres de chemin et paramètres de requête dans la même fonction, **FastAPI** saura comment les gérer.
Vous pouvez déclarer plusieurs paramètres de chemin et paramètres de requête dans la même fonction, **FastAPI** saura comment les gérer.
Et vous n'avez pas besoin de les déclarer dans un ordre spécifique.

View File

@@ -5,13 +5,15 @@ theme:
name: material
custom_dir: overrides
palette:
- scheme: default
- media: "(prefers-color-scheme: light)"
scheme: default
primary: teal
accent: amber
toggle:
icon: material/lightbulb
name: Switch to light mode
- scheme: slate
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: teal
accent: amber
toggle:

View File

@@ -321,7 +321,7 @@ And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" targe
### Recap
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
You do that with standard modern Python types.
@@ -378,7 +378,7 @@ Coming back to the previous code example, **FastAPI** will:
* 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 `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.

View File

@@ -5,13 +5,15 @@ theme:
name: material
custom_dir: overrides
palette:
- scheme: default
- media: "(prefers-color-scheme: light)"
scheme: default
primary: teal
accent: amber
toggle:
icon: material/lightbulb
name: Switch to light mode
- scheme: slate
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: teal
accent: amber
toggle:

View File

@@ -318,7 +318,7 @@ And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" targe
### Recap
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
You do that with standard modern Python types.
@@ -375,7 +375,7 @@ Coming back to the previous code example, **FastAPI** will:
* 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 `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.

View File

@@ -5,13 +5,15 @@ theme:
name: material
custom_dir: overrides
palette:
- scheme: default
- media: "(prefers-color-scheme: light)"
scheme: default
primary: teal
accent: amber
toggle:
icon: material/lightbulb
name: Switch to light mode
- scheme: slate
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: teal
accent: amber
toggle:

Some files were not shown because too many files have changed in this diff Show More