diff --git a/README.md b/README.md
index 39030ef52..8baee7825 100644
--- a/README.md
+++ b/README.md
@@ -46,17 +46,15 @@ The key features are:
-
-
-
+
diff --git a/docs/az/mkdocs.yml b/docs/az/mkdocs.yml
index 7f4a490d8..7d59451c1 100644
--- a/docs/az/mkdocs.yml
+++ b/docs/az/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -105,6 +106,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/de/mkdocs.yml b/docs/de/mkdocs.yml
index f6e0a6b01..87fe74697 100644
--- a/docs/de/mkdocs.yml
+++ b/docs/de/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -106,6 +107,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/em/docs/advanced/additional-responses.md b/docs/em/docs/advanced/additional-responses.md
new file mode 100644
index 000000000..26963c2e3
--- /dev/null
+++ b/docs/em/docs/advanced/additional-responses.md
@@ -0,0 +1,240 @@
+# 🌖 📨 🗄
+
+!!! warning
+ 👉 👍 🏧 ❔.
+
+ 🚥 👆 ▶️ ⏮️ **FastAPI**, 👆 💪 🚫 💪 👉.
+
+👆 💪 📣 🌖 📨, ⏮️ 🌖 👔 📟, 🔉 🆎, 📛, ♒️.
+
+👈 🌖 📨 🔜 🔌 🗄 🔗, 👫 🔜 😑 🛠️ 🩺.
+
+✋️ 👈 🌖 📨 👆 ✔️ ⚒ 💭 👆 📨 `Response` 💖 `JSONResponse` 🔗, ⏮️ 👆 👔 📟 & 🎚.
+
+## 🌖 📨 ⏮️ `model`
+
+👆 💪 🚶♀️ 👆 *➡ 🛠️ 👨🎨* 🔢 `responses`.
+
+⚫️ 📨 `dict`, 🔑 👔 📟 🔠 📨, 💖 `200`, & 💲 🎏 `dict`Ⓜ ⏮️ ℹ 🔠 👫.
+
+🔠 👈 📨 `dict`Ⓜ 💪 ✔️ 🔑 `model`, ⚗ Pydantic 🏷, 💖 `response_model`.
+
+**FastAPI** 🔜 ✊ 👈 🏷, 🏗 🚮 🎻 🔗 & 🔌 ⚫️ ☑ 🥉 🗄.
+
+🖼, 📣 ➕1️⃣ 📨 ⏮️ 👔 📟 `404` & Pydantic 🏷 `Message`, 👆 💪 ✍:
+
+```Python hl_lines="18 22"
+{!../../../docs_src/additional_responses/tutorial001.py!}
+```
+
+!!! note
+ ✔️ 🤯 👈 👆 ✔️ 📨 `JSONResponse` 🔗.
+
+!!! info
+ `model` 🔑 🚫 🍕 🗄.
+
+ **FastAPI** 🔜 ✊ Pydantic 🏷 ⚪️➡️ 📤, 🏗 `JSON Schema`, & 🚮 ⚫️ ☑ 🥉.
+
+ ☑ 🥉:
+
+ * 🔑 `content`, 👈 ✔️ 💲 ➕1️⃣ 🎻 🎚 (`dict`) 👈 🔌:
+ * 🔑 ⏮️ 📻 🆎, ✅ `application/json`, 👈 🔌 💲 ➕1️⃣ 🎻 🎚, 👈 🔌:
+ * 🔑 `schema`, 👈 ✔️ 💲 🎻 🔗 ⚪️➡️ 🏷, 📥 ☑ 🥉.
+ * **FastAPI** 🚮 🔗 📥 🌐 🎻 🔗 ➕1️⃣ 🥉 👆 🗄 ↩️ ✅ ⚫️ 🔗. 👉 🌌, 🎏 🈸 & 👩💻 💪 ⚙️ 👈 🎻 🔗 🔗, 🚚 👻 📟 ⚡ 🧰, ♒️.
+
+🏗 📨 🗄 👉 *➡ 🛠️* 🔜:
+
+```JSON hl_lines="3-12"
+{
+ "responses": {
+ "404": {
+ "description": "Additional Response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Message"
+ }
+ }
+ }
+ },
+ "200": {
+ "description": "Successful Response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Item"
+ }
+ }
+ }
+ },
+ "422": {
+ "description": "Validation Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/HTTPValidationError"
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+🔗 🔗 ➕1️⃣ 🥉 🔘 🗄 🔗:
+
+```JSON hl_lines="4-16"
+{
+ "components": {
+ "schemas": {
+ "Message": {
+ "title": "Message",
+ "required": [
+ "message"
+ ],
+ "type": "object",
+ "properties": {
+ "message": {
+ "title": "Message",
+ "type": "string"
+ }
+ }
+ },
+ "Item": {
+ "title": "Item",
+ "required": [
+ "id",
+ "value"
+ ],
+ "type": "object",
+ "properties": {
+ "id": {
+ "title": "Id",
+ "type": "string"
+ },
+ "value": {
+ "title": "Value",
+ "type": "string"
+ }
+ }
+ },
+ "ValidationError": {
+ "title": "ValidationError",
+ "required": [
+ "loc",
+ "msg",
+ "type"
+ ],
+ "type": "object",
+ "properties": {
+ "loc": {
+ "title": "Location",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "msg": {
+ "title": "Message",
+ "type": "string"
+ },
+ "type": {
+ "title": "Error Type",
+ "type": "string"
+ }
+ }
+ },
+ "HTTPValidationError": {
+ "title": "HTTPValidationError",
+ "type": "object",
+ "properties": {
+ "detail": {
+ "title": "Detail",
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/ValidationError"
+ }
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+## 🌖 🔉 🆎 👑 📨
+
+👆 💪 ⚙️ 👉 🎏 `responses` 🔢 🚮 🎏 🔉 🆎 🎏 👑 📨.
+
+🖼, 👆 💪 🚮 🌖 📻 🆎 `image/png`, 📣 👈 👆 *➡ 🛠️* 💪 📨 🎻 🎚 (⏮️ 📻 🆎 `application/json`) ⚖️ 🇩🇴 🖼:
+
+```Python hl_lines="19-24 28"
+{!../../../docs_src/additional_responses/tutorial002.py!}
+```
+
+!!! note
+ 👀 👈 👆 ✔️ 📨 🖼 ⚙️ `FileResponse` 🔗.
+
+!!! info
+ 🚥 👆 ✔ 🎏 📻 🆎 🎯 👆 `responses` 🔢, FastAPI 🔜 🤔 📨 ✔️ 🎏 📻 🆎 👑 📨 🎓 (🔢 `application/json`).
+
+ ✋️ 🚥 👆 ✔️ ✔ 🛃 📨 🎓 ⏮️ `None` 🚮 📻 🆎, FastAPI 🔜 ⚙️ `application/json` 🙆 🌖 📨 👈 ✔️ 👨💼 🏷.
+
+## 🌀 ℹ
+
+👆 💪 🌀 📨 ℹ ⚪️➡️ 💗 🥉, 🔌 `response_model`, `status_code`, & `responses` 🔢.
+
+👆 💪 📣 `response_model`, ⚙️ 🔢 👔 📟 `200` (⚖️ 🛃 1️⃣ 🚥 👆 💪), & ⤴️ 📣 🌖 ℹ 👈 🎏 📨 `responses`, 🔗 🗄 🔗.
+
+**FastAPI** 🔜 🚧 🌖 ℹ ⚪️➡️ `responses`, & 🌀 ⚫️ ⏮️ 🎻 🔗 ⚪️➡️ 👆 🏷.
+
+🖼, 👆 💪 📣 📨 ⏮️ 👔 📟 `404` 👈 ⚙️ Pydantic 🏷 & ✔️ 🛃 `description`.
+
+& 📨 ⏮️ 👔 📟 `200` 👈 ⚙️ 👆 `response_model`, ✋️ 🔌 🛃 `example`:
+
+```Python hl_lines="20-31"
+{!../../../docs_src/additional_responses/tutorial003.py!}
+```
+
+⚫️ 🔜 🌐 🌀 & 🔌 👆 🗄, & 🎦 🛠️ 🩺:
+
+
+
+## 🌀 🔢 📨 & 🛃 🕐
+
+👆 💪 💚 ✔️ 🔁 📨 👈 ✔ 📚 *➡ 🛠️*, ✋️ 👆 💚 🌀 👫 ⏮️ 🛃 📨 💚 🔠 *➡ 🛠️*.
+
+📚 💼, 👆 💪 ⚙️ 🐍 ⚒ "🏗" `dict` ⏮️ `**dict_to_unpack`:
+
+```Python
+old_dict = {
+ "old key": "old value",
+ "second old key": "second old value",
+}
+new_dict = {**old_dict, "new key": "new value"}
+```
+
+📥, `new_dict` 🔜 🔌 🌐 🔑-💲 👫 ⚪️➡️ `old_dict` ➕ 🆕 🔑-💲 👫:
+
+```Python
+{
+ "old key": "old value",
+ "second old key": "second old value",
+ "new key": "new value",
+}
+```
+
+👆 💪 ⚙️ 👈 ⚒ 🏤-⚙️ 🔢 📨 👆 *➡ 🛠️* & 🌀 👫 ⏮️ 🌖 🛃 🕐.
+
+🖼:
+
+```Python hl_lines="13-17 26"
+{!../../../docs_src/additional_responses/tutorial004.py!}
+```
+
+## 🌖 ℹ 🔃 🗄 📨
+
+👀 ⚫️❔ ⚫️❔ 👆 💪 🔌 📨, 👆 💪 ✅ 👉 📄 🗄 🔧:
+
+* 🗄 📨 🎚, ⚫️ 🔌 `Response Object`.
+* 🗄 📨 🎚, 👆 💪 🔌 🕳 ⚪️➡️ 👉 🔗 🔠 📨 🔘 👆 `responses` 🔢. ✅ `description`, `headers`, `content` (🔘 👉 👈 👆 📣 🎏 🔉 🆎 & 🎻 🔗), & `links`.
diff --git a/docs/em/docs/advanced/additional-status-codes.md b/docs/em/docs/advanced/additional-status-codes.md
new file mode 100644
index 000000000..392579df6
--- /dev/null
+++ b/docs/em/docs/advanced/additional-status-codes.md
@@ -0,0 +1,37 @@
+# 🌖 👔 📟
+
+🔢, **FastAPI** 🔜 📨 📨 ⚙️ `JSONResponse`, 🚮 🎚 👆 📨 ⚪️➡️ 👆 *➡ 🛠️* 🔘 👈 `JSONResponse`.
+
+⚫️ 🔜 ⚙️ 🔢 👔 📟 ⚖️ 1️⃣ 👆 ⚒ 👆 *➡ 🛠️*.
+
+## 🌖 👔 📟
+
+🚥 👆 💚 📨 🌖 👔 📟 ↖️ ⚪️➡️ 👑 1️⃣, 👆 💪 👈 🛬 `Response` 🔗, 💖 `JSONResponse`, & ⚒ 🌖 👔 📟 🔗.
+
+🖼, ➡️ 💬 👈 👆 💚 ✔️ *➡ 🛠️* 👈 ✔ ℹ 🏬, & 📨 🇺🇸🔍 👔 📟 2️⃣0️⃣0️⃣ "👌" 🕐❔ 🏆.
+
+✋️ 👆 💚 ⚫️ 🚫 🆕 🏬. & 🕐❔ 🏬 🚫 🔀 ⏭, ⚫️ ✍ 👫, & 📨 🇺🇸🔍 👔 📟 2️⃣0️⃣1️⃣ "✍".
+
+🏆 👈, 🗄 `JSONResponse`, & 📨 👆 🎚 📤 🔗, ⚒ `status_code` 👈 👆 💚:
+
+```Python hl_lines="4 25"
+{!../../../docs_src/additional_status_codes/tutorial001.py!}
+```
+
+!!! warning
+ 🕐❔ 👆 📨 `Response` 🔗, 💖 🖼 🔛, ⚫️ 🔜 📨 🔗.
+
+ ⚫️ 🏆 🚫 🎻 ⏮️ 🏷, ♒️.
+
+ ⚒ 💭 ⚫️ ✔️ 📊 👆 💚 ⚫️ ✔️, & 👈 💲 ☑ 🎻 (🚥 👆 ⚙️ `JSONResponse`).
+
+!!! note "📡 ℹ"
+ 👆 💪 ⚙️ `from starlette.responses import JSONResponse`.
+
+ **FastAPI** 🚚 🎏 `starlette.responses` `fastapi.responses` 🏪 👆, 👩💻. ✋️ 🌅 💪 📨 👟 🔗 ⚪️➡️ 💃. 🎏 ⏮️ `status`.
+
+## 🗄 & 🛠️ 🩺
+
+🚥 👆 📨 🌖 👔 📟 & 📨 🔗, 👫 🏆 🚫 🔌 🗄 🔗 (🛠️ 🩺), ↩️ FastAPI 🚫 ✔️ 🌌 💭 ⏪ ⚫️❔ 👆 🚶 📨.
+
+✋️ 👆 💪 📄 👈 👆 📟, ⚙️: [🌖 📨](additional-responses.md){.internal-link target=_blank}.
diff --git a/docs/em/docs/advanced/advanced-dependencies.md b/docs/em/docs/advanced/advanced-dependencies.md
new file mode 100644
index 000000000..fa1554734
--- /dev/null
+++ b/docs/em/docs/advanced/advanced-dependencies.md
@@ -0,0 +1,70 @@
+# 🏧 🔗
+
+## 🔗 🔗
+
+🌐 🔗 👥 ✔️ 👀 🔧 🔢 ⚖️ 🎓.
+
+✋️ 📤 💪 💼 🌐❔ 👆 💚 💪 ⚒ 🔢 🔛 🔗, 🍵 ✔️ 📣 📚 🎏 🔢 ⚖️ 🎓.
+
+➡️ 🌈 👈 👥 💚 ✔️ 🔗 👈 ✅ 🚥 🔢 🔢 `q` 🔌 🔧 🎚.
+
+✋️ 👥 💚 💪 🔗 👈 🔧 🎚.
+
+## "🇧🇲" 👐
+
+🐍 📤 🌌 ⚒ 👐 🎓 "🇧🇲".
+
+🚫 🎓 ⚫️ (❔ ⏪ 🇧🇲), ✋️ 👐 👈 🎓.
+
+👈, 👥 📣 👩🔬 `__call__`:
+
+```Python hl_lines="10"
+{!../../../docs_src/dependencies/tutorial011.py!}
+```
+
+👉 💼, 👉 `__call__` ⚫️❔ **FastAPI** 🔜 ⚙️ ✅ 🌖 🔢 & 🎧-🔗, & 👉 ⚫️❔ 🔜 🤙 🚶♀️ 💲 🔢 👆 *➡ 🛠️ 🔢* ⏪.
+
+## 🔗 👐
+
+& 🔜, 👥 💪 ⚙️ `__init__` 📣 🔢 👐 👈 👥 💪 ⚙️ "🔗" 🔗:
+
+```Python hl_lines="7"
+{!../../../docs_src/dependencies/tutorial011.py!}
+```
+
+👉 💼, **FastAPI** 🏆 🚫 ⏱ 👆 ⚖️ 💅 🔃 `__init__`, 👥 🔜 ⚙️ ⚫️ 🔗 👆 📟.
+
+## ✍ 👐
+
+👥 💪 ✍ 👐 👉 🎓 ⏮️:
+
+```Python hl_lines="16"
+{!../../../docs_src/dependencies/tutorial011.py!}
+```
+
+& 👈 🌌 👥 💪 "🔗" 👆 🔗, 👈 🔜 ✔️ `"bar"` 🔘 ⚫️, 🔢 `checker.fixed_content`.
+
+## ⚙️ 👐 🔗
+
+⤴️, 👥 💪 ⚙️ 👉 `checker` `Depends(checker)`, ↩️ `Depends(FixedContentQueryChecker)`, ↩️ 🔗 👐, `checker`, 🚫 🎓 ⚫️.
+
+& 🕐❔ ❎ 🔗, **FastAPI** 🔜 🤙 👉 `checker` 💖:
+
+```Python
+checker(q="somequery")
+```
+
+...& 🚶♀️ ⚫️❔ 👈 📨 💲 🔗 👆 *➡ 🛠️ 🔢* 🔢 `fixed_content_included`:
+
+```Python hl_lines="20"
+{!../../../docs_src/dependencies/tutorial011.py!}
+```
+
+!!! tip
+ 🌐 👉 💪 😑 🎭. & ⚫️ 💪 🚫 📶 🆑 ❔ ⚫️ ⚠.
+
+ 👫 🖼 😫 🙅, ✋️ 🎦 ❔ ⚫️ 🌐 👷.
+
+ 📃 🔃 💂♂, 📤 🚙 🔢 👈 🛠️ 👉 🎏 🌌.
+
+ 🚥 👆 🤔 🌐 👉, 👆 ⏪ 💭 ❔ 👈 🚙 🧰 💂♂ 👷 🔘.
diff --git a/docs/em/docs/advanced/async-sql-databases.md b/docs/em/docs/advanced/async-sql-databases.md
new file mode 100644
index 000000000..848936de1
--- /dev/null
+++ b/docs/em/docs/advanced/async-sql-databases.md
@@ -0,0 +1,162 @@
+# 🔁 🗄 (🔗) 💽
+
+👆 💪 ⚙️ `encode/databases` ⏮️ **FastAPI** 🔗 💽 ⚙️ `async` & `await`.
+
+⚫️ 🔗 ⏮️:
+
+* ✳
+* ✳
+* 🗄
+
+👉 🖼, 👥 🔜 ⚙️ **🗄**, ↩️ ⚫️ ⚙️ 👁 📁 & 🐍 ✔️ 🛠️ 🐕🦺. , 👆 💪 📁 👉 🖼 & 🏃 ⚫️.
+
+⏪, 👆 🏭 🈸, 👆 💪 💚 ⚙️ 💽 💽 💖 **✳**.
+
+!!! tip
+ 👆 💪 🛠️ 💭 ⚪️➡️ 📄 🔃 🇸🇲 🐜 ([🗄 (🔗) 💽](../tutorial/sql-databases.md){.internal-link target=_blank}), 💖 ⚙️ 🚙 🔢 🎭 🛠️ 💽, 🔬 👆 **FastAPI** 📟.
+
+ 👉 📄 🚫 ✔ 📚 💭, 🌓 😑 💃.
+
+## 🗄 & ⚒ 🆙 `SQLAlchemy`
+
+* 🗄 `SQLAlchemy`.
+* ✍ `metadata` 🎚.
+* ✍ 🏓 `notes` ⚙️ `metadata` 🎚.
+
+```Python hl_lines="4 14 16-22"
+{!../../../docs_src/async_sql_databases/tutorial001.py!}
+```
+
+!!! tip
+ 👀 👈 🌐 👉 📟 😁 🇸🇲 🐚.
+
+ `databases` 🚫 🔨 🕳 📥.
+
+## 🗄 & ⚒ 🆙 `databases`
+
+* 🗄 `databases`.
+* ✍ `DATABASE_URL`.
+* ✍ `database` 🎚.
+
+```Python hl_lines="3 9 12"
+{!../../../docs_src/async_sql_databases/tutorial001.py!}
+```
+
+!!! tip
+ 🚥 👆 🔗 🎏 💽 (✅ ✳), 👆 🔜 💪 🔀 `DATABASE_URL`.
+
+## ✍ 🏓
+
+👉 💼, 👥 🏗 🏓 🎏 🐍 📁, ✋️ 🏭, 👆 🔜 🎲 💚 ✍ 👫 ⏮️ ⚗, 🛠️ ⏮️ 🛠️, ♒️.
+
+📥, 👉 📄 🔜 🏃 🔗, ▶️️ ⏭ ▶️ 👆 **FastAPI** 🈸.
+
+* ✍ `engine`.
+* ✍ 🌐 🏓 ⚪️➡️ `metadata` 🎚.
+
+```Python hl_lines="25-28"
+{!../../../docs_src/async_sql_databases/tutorial001.py!}
+```
+
+## ✍ 🏷
+
+✍ Pydantic 🏷:
+
+* 🗒 ✍ (`NoteIn`).
+* 🗒 📨 (`Note`).
+
+```Python hl_lines="31-33 36-39"
+{!../../../docs_src/async_sql_databases/tutorial001.py!}
+```
+
+🏗 👫 Pydantic 🏷, 🔢 💽 🔜 ✔, 🎻 (🗜), & ✍ (📄).
+
+, 👆 🔜 💪 👀 ⚫️ 🌐 🎓 🛠️ 🩺.
+
+## 🔗 & 🔌
+
+* ✍ 👆 `FastAPI` 🈸.
+* ✍ 🎉 🐕🦺 🔗 & 🔌 ⚪️➡️ 💽.
+
+```Python hl_lines="42 45-47 50-52"
+{!../../../docs_src/async_sql_databases/tutorial001.py!}
+```
+
+## ✍ 🗒
+
+✍ *➡ 🛠️ 🔢* ✍ 🗒:
+
+```Python hl_lines="55-58"
+{!../../../docs_src/async_sql_databases/tutorial001.py!}
+```
+
+!!! Note
+ 👀 👈 👥 🔗 ⏮️ 💽 ⚙️ `await`, *➡ 🛠️ 🔢* 📣 ⏮️ `async`.
+
+### 👀 `response_model=List[Note]`
+
+⚫️ ⚙️ `typing.List`.
+
+👈 📄 (& ✔, 🎻, ⛽) 🔢 💽, `list` `Note`Ⓜ.
+
+## ✍ 🗒
+
+✍ *➡ 🛠️ 🔢* ✍ 🗒:
+
+```Python hl_lines="61-65"
+{!../../../docs_src/async_sql_databases/tutorial001.py!}
+```
+
+!!! Note
+ 👀 👈 👥 🔗 ⏮️ 💽 ⚙️ `await`, *➡ 🛠️ 🔢* 📣 ⏮️ `async`.
+
+### 🔃 `{**note.dict(), "id": last_record_id}`
+
+`note` Pydantic `Note` 🎚.
+
+`note.dict()` 📨 `dict` ⏮️ 🚮 💽, 🕳 💖:
+
+```Python
+{
+ "text": "Some note",
+ "completed": False,
+}
+```
+
+✋️ ⚫️ 🚫 ✔️ `id` 🏑.
+
+👥 ✍ 🆕 `dict`, 👈 🔌 🔑-💲 👫 ⚪️➡️ `note.dict()` ⏮️:
+
+```Python
+{**note.dict()}
+```
+
+`**note.dict()` "unpacks" the key value pairs directly, so, `{**note.dict()}` would be, more or less, a copy of `note.dict()`.
+
+& ⤴️, 👥 ↔ 👈 📁 `dict`, ❎ ➕1️⃣ 🔑-💲 👫: `"id": last_record_id`:
+
+```Python
+{**note.dict(), "id": last_record_id}
+```
+
+, 🏁 🏁 📨 🔜 🕳 💖:
+
+```Python
+{
+ "id": 1,
+ "text": "Some note",
+ "completed": False,
+}
+```
+
+## ✅ ⚫️
+
+👆 💪 📁 👉 📟, & 👀 🩺 http://127.0.0.1:8000/docs.
+
+📤 👆 💪 👀 🌐 👆 🛠️ 📄 & 🔗 ⏮️ ⚫️:
+
+
+
+## 🌅 ℹ
+
+👆 💪 ✍ 🌅 🔃 `encode/databases` 🚮 📂 📃.
diff --git a/docs/em/docs/advanced/async-tests.md b/docs/em/docs/advanced/async-tests.md
new file mode 100644
index 000000000..df94c6ce7
--- /dev/null
+++ b/docs/em/docs/advanced/async-tests.md
@@ -0,0 +1,92 @@
+# 🔁 💯
+
+👆 ✔️ ⏪ 👀 ❔ 💯 👆 **FastAPI** 🈸 ⚙️ 🚚 `TestClient`. 🆙 🔜, 👆 ✔️ 🕴 👀 ❔ ✍ 🔁 💯, 🍵 ⚙️ `async` 🔢.
+
+➖ 💪 ⚙️ 🔁 🔢 👆 💯 💪 ⚠, 🖼, 🕐❔ 👆 🔬 👆 💽 🔁. 🌈 👆 💚 💯 📨 📨 👆 FastAPI 🈸 & ⤴️ ✔ 👈 👆 👩💻 ⏪ ✍ ☑ 💽 💽, ⏪ ⚙️ 🔁 💽 🗃.
+
+➡️ 👀 ❔ 👥 💪 ⚒ 👈 👷.
+
+## pytest.mark.anyio
+
+🚥 👥 💚 🤙 🔁 🔢 👆 💯, 👆 💯 🔢 ✔️ 🔁. AnyIO 🚚 👌 📁 👉, 👈 ✔ 👥 ✔ 👈 💯 🔢 🤙 🔁.
+
+## 🇸🇲
+
+🚥 👆 **FastAPI** 🈸 ⚙️ 😐 `def` 🔢 ↩️ `async def`, ⚫️ `async` 🈸 🔘.
+
+`TestClient` 🔨 🎱 🔘 🤙 🔁 FastAPI 🈸 👆 😐 `def` 💯 🔢, ⚙️ 🐩 ✳. ✋️ 👈 🎱 🚫 👷 🚫🔜 🕐❔ 👥 ⚙️ ⚫️ 🔘 🔁 🔢. 🏃 👆 💯 🔁, 👥 💪 🙅♂ 📏 ⚙️ `TestClient` 🔘 👆 💯 🔢.
+
+`TestClient` ⚓️ 🔛 🇸🇲, & ↩️, 👥 💪 ⚙️ ⚫️ 🔗 💯 🛠️.
+
+## 🖼
+
+🙅 🖼, ➡️ 🤔 📁 📊 🎏 1️⃣ 🔬 [🦏 🈸](../tutorial/bigger-applications.md){.internal-link target=_blank} & [🔬](../tutorial/testing.md){.internal-link target=_blank}:
+
+```
+.
+├── app
+│ ├── __init__.py
+│ ├── main.py
+│ └── test_main.py
+```
+
+📁 `main.py` 🔜 ✔️:
+
+```Python
+{!../../../docs_src/async_tests/main.py!}
+```
+
+📁 `test_main.py` 🔜 ✔️ 💯 `main.py`, ⚫️ 💪 👀 💖 👉 🔜:
+
+```Python
+{!../../../docs_src/async_tests/test_main.py!}
+```
+
+## 🏃 ⚫️
+
+👆 💪 🏃 👆 💯 🐌 📨:
+
+
+
+✋️ 🚥 👥 🔐 🩺 🎚 "🛂" 📛 ⚙️ 🗳 ⏮️ ⛴ `9999`, `/api/v1/docs`, ⚫️ 👷 ☑ ❗ 👶
+
+👆 💪 ✅ ⚫️ http://127.0.0.1:9999/api/v1/docs:
+
+
+
+▶️️ 👥 💚 ⚫️. 👶 👶
+
+👉 ↩️ FastAPI ⚙️ 👉 `root_path` ✍ 🔢 `server` 🗄 ⏮️ 📛 🚚 `root_path`.
+
+## 🌖 💽
+
+!!! warning
+ 👉 🌅 🏧 ⚙️ 💼. 💭 🆓 🚶 ⚫️.
+
+🔢, **FastAPI** 🔜 ✍ `server` 🗄 🔗 ⏮️ 📛 `root_path`.
+
+✋️ 👆 💪 🚚 🎏 🎛 `servers`, 🖼 🚥 👆 💚 *🎏* 🩺 🎚 🔗 ⏮️ 🏗 & 🏭 🌐.
+
+🚥 👆 🚶♀️ 🛃 📇 `servers` & 📤 `root_path` (↩️ 👆 🛠️ 👨❤👨 ⛅ 🗳), **FastAPI** 🔜 📩 "💽" ⏮️ 👉 `root_path` ▶️ 📇.
+
+🖼:
+
+```Python hl_lines="4-7"
+{!../../../docs_src/behind_a_proxy/tutorial003.py!}
+```
+
+🔜 🏗 🗄 🔗 💖:
+
+```JSON hl_lines="5-7"
+{
+ "openapi": "3.0.2",
+ // More stuff here
+ "servers": [
+ {
+ "url": "/api/v1"
+ },
+ {
+ "url": "https://stag.example.com",
+ "description": "Staging environment"
+ },
+ {
+ "url": "https://prod.example.com",
+ "description": "Production environment"
+ }
+ ],
+ "paths": {
+ // More stuff here
+ }
+}
+```
+
+!!! tip
+ 👀 🚘-🏗 💽 ⏮️ `url` 💲 `/api/v1`, ✊ ⚪️➡️ `root_path`.
+
+🩺 🎚 http://127.0.0.1:9999/api/v1/docs ⚫️ 🔜 👀 💖:
+
+
+
+!!! tip
+ 🩺 🎚 🔜 🔗 ⏮️ 💽 👈 👆 🖊.
+
+### ❎ 🏧 💽 ⚪️➡️ `root_path`
+
+🚥 👆 🚫 💚 **FastAPI** 🔌 🏧 💽 ⚙️ `root_path`, 👆 💪 ⚙️ 🔢 `root_path_in_servers=False`:
+
+```Python hl_lines="9"
+{!../../../docs_src/behind_a_proxy/tutorial004.py!}
+```
+
+& ⤴️ ⚫️ 🏆 🚫 🔌 ⚫️ 🗄 🔗.
+
+## 🗜 🎧-🈸
+
+🚥 👆 💪 🗻 🎧-🈸 (🔬 [🎧 🈸 - 🗻](./sub-applications.md){.internal-link target=_blank}) ⏪ ⚙️ 🗳 ⏮️ `root_path`, 👆 💪 ⚫️ 🛎, 👆 🔜 ⌛.
+
+FastAPI 🔜 🔘 ⚙️ `root_path` 🎆, ⚫️ 🔜 👷. 👶
diff --git a/docs/em/docs/advanced/conditional-openapi.md b/docs/em/docs/advanced/conditional-openapi.md
new file mode 100644
index 000000000..a17ba4eec
--- /dev/null
+++ b/docs/em/docs/advanced/conditional-openapi.md
@@ -0,0 +1,58 @@
+# 🎲 🗄
+
+🚥 👆 💪, 👆 💪 ⚙️ ⚒ & 🌐 🔢 🔗 🗄 ✔ ⚓️ 🔛 🌐, & ❎ ⚫️ 🍕.
+
+## 🔃 💂♂, 🔗, & 🩺
+
+🕵♂ 👆 🧾 👩💻 🔢 🏭 *🚫🔜 🚫* 🌌 🛡 👆 🛠️.
+
+👈 🚫 🚮 🙆 ➕ 💂♂ 👆 🛠️, *➡ 🛠️* 🔜 💪 🌐❔ 👫.
+
+🚥 📤 💂♂ ⚠ 👆 📟, ⚫️ 🔜 🔀.
+
+🕵♂ 🧾 ⚒ ⚫️ 🌅 ⚠ 🤔 ❔ 🔗 ⏮️ 👆 🛠️, & 💪 ⚒ ⚫️ 🌅 ⚠ 👆 ℹ ⚫️ 🏭. ⚫️ 💪 🤔 🎯 📨 💂♂ 🔘 🌌.
+
+🚥 👆 💚 🔐 👆 🛠️, 📤 📚 👍 👜 👆 💪, 🖼:
+
+* ⚒ 💭 👆 ✔️ 👍 🔬 Pydantic 🏷 👆 📨 💪 & 📨.
+* 🔗 🙆 ✔ ✔ & 🔑 ⚙️ 🔗.
+* 🙅 🏪 🔢 🔐, 🕴 🔐#️⃣.
+* 🛠️ & ⚙️ 👍-💭 🔐 🧰, 💖 🇸🇲 & 🥙 🤝, ♒️.
+* 🚮 🌅 🧽 ✔ 🎛 ⏮️ Oauth2️⃣ ↔ 🌐❔ 💪.
+* ...♒️.
+
+👐, 👆 5️⃣📆 ✔️ 📶 🎯 ⚙️ 💼 🌐❔ 👆 🤙 💪 ❎ 🛠️ 🩺 🌐 (✅ 🏭) ⚖️ ⚓️ 🔛 📳 ⚪️➡️ 🌐 🔢.
+
+## 🎲 🗄 ⚪️➡️ ⚒ & 🇨🇻 {
+
+👆 💪 💪 ⚙️ 🎏 Pydantic ⚒ 🔗 👆 🏗 🗄 & 🩺 ⚜.
+
+🖼:
+
+```Python hl_lines="6 11"
+{!../../../docs_src/conditional_openapi/tutorial001.py!}
+```
+
+📥 👥 📣 ⚒ `openapi_url` ⏮️ 🎏 🔢 `"/openapi.json"`.
+
+& ⤴️ 👥 ⚙️ ⚫️ 🕐❔ 🏗 `FastAPI` 📱.
+
+⤴️ 👆 💪 ❎ 🗄 (✅ 🎚 🩺) ⚒ 🌐 🔢 `OPENAPI_URL` 🛁 🎻, 💖:
+
+
+
+## 💪 📨
+
+📥 💪 📨.
+
+✔️ 🤯 👈 👆 💪 ⚙️ `Response` 📨 🕳 🙆, ⚖️ ✍ 🛃 🎧-🎓.
+
+!!! note "📡 ℹ"
+ 👆 💪 ⚙️ `from starlette.responses import HTMLResponse`.
+
+ **FastAPI** 🚚 🎏 `starlette.responses` `fastapi.responses` 🏪 👆, 👩💻. ✋️ 🌅 💪 📨 👟 🔗 ⚪️➡️ 💃.
+
+### `Response`
+
+👑 `Response` 🎓, 🌐 🎏 📨 😖 ⚪️➡️ ⚫️.
+
+👆 💪 📨 ⚫️ 🔗.
+
+⚫️ 🚫 📄 🔢:
+
+* `content` - `str` ⚖️ `bytes`.
+* `status_code` - `int` 🇺🇸🔍 👔 📟.
+* `headers` - `dict` 🎻.
+* `media_type` - `str` 🤝 📻 🆎. 🤶 Ⓜ. `"text/html"`.
+
+FastAPI (🤙 💃) 🔜 🔁 🔌 🎚-📐 🎚. ⚫️ 🔜 🔌 🎚-🆎 🎚, ⚓️ 🔛 = & 🔁 = ✍ 🆎.
+
+```Python hl_lines="1 18"
+{!../../../docs_src/response_directly/tutorial002.py!}
+```
+
+### `HTMLResponse`
+
+✊ ✍ ⚖️ 🔢 & 📨 🕸 📨, 👆 ✍ 🔛.
+
+### `PlainTextResponse`
+
+✊ ✍ ⚖️ 🔢 & 📨 ✅ ✍ 📨.
+
+```Python hl_lines="2 7 9"
+{!../../../docs_src/custom_response/tutorial005.py!}
+```
+
+### `JSONResponse`
+
+✊ 💽 & 📨 `application/json` 🗜 📨.
+
+👉 🔢 📨 ⚙️ **FastAPI**, 👆 ✍ 🔛.
+
+### `ORJSONResponse`
+
+⏩ 🎛 🎻 📨 ⚙️ `orjson`, 👆 ✍ 🔛.
+
+### `UJSONResponse`
+
+🎛 🎻 📨 ⚙️ `ujson`.
+
+!!! warning
+ `ujson` 🌘 💛 🌘 🐍 🏗-🛠️ ❔ ⚫️ 🍵 📐-💼.
+
+```Python hl_lines="2 7"
+{!../../../docs_src/custom_response/tutorial001.py!}
+```
+
+!!! tip
+ ⚫️ 💪 👈 `ORJSONResponse` 💪 ⏩ 🎛.
+
+### `RedirectResponse`
+
+📨 🇺🇸🔍 ❎. ⚙️ 3️⃣0️⃣7️⃣ 👔 📟 (🍕 ❎) 🔢.
+
+👆 💪 📨 `RedirectResponse` 🔗:
+
+```Python hl_lines="2 9"
+{!../../../docs_src/custom_response/tutorial006.py!}
+```
+
+---
+
+⚖️ 👆 💪 ⚙️ ⚫️ `response_class` 🔢:
+
+
+```Python hl_lines="2 7 9"
+{!../../../docs_src/custom_response/tutorial006b.py!}
+```
+
+🚥 👆 👈, ⤴️ 👆 💪 📨 📛 🔗 ⚪️➡️ 👆 *➡ 🛠️* 🔢.
+
+👉 💼, `status_code` ⚙️ 🔜 🔢 1️⃣ `RedirectResponse`, ❔ `307`.
+
+---
+
+👆 💪 ⚙️ `status_code` 🔢 🌀 ⏮️ `response_class` 🔢:
+
+```Python hl_lines="2 7 9"
+{!../../../docs_src/custom_response/tutorial006c.py!}
+```
+
+### `StreamingResponse`
+
+✊ 🔁 🚂 ⚖️ 😐 🚂/🎻 & 🎏 📨 💪.
+
+```Python hl_lines="2 14"
+{!../../../docs_src/custom_response/tutorial007.py!}
+```
+
+#### ⚙️ `StreamingResponse` ⏮️ 📁-💖 🎚
+
+🚥 👆 ✔️ 📁-💖 🎚 (✅ 🎚 📨 `open()`), 👆 💪 ✍ 🚂 🔢 🔁 🤭 👈 📁-💖 🎚.
+
+👈 🌌, 👆 🚫 ✔️ ✍ ⚫️ 🌐 🥇 💾, & 👆 💪 🚶♀️ 👈 🚂 🔢 `StreamingResponse`, & 📨 ⚫️.
+
+👉 🔌 📚 🗃 🔗 ⏮️ ☁ 💾, 📹 🏭, & 🎏.
+
+```{ .python .annotate hl_lines="2 10-12 14" }
+{!../../../docs_src/custom_response/tutorial008.py!}
+```
+
+1️⃣. 👉 🚂 🔢. ⚫️ "🚂 🔢" ↩️ ⚫️ 🔌 `yield` 📄 🔘.
+2️⃣. ⚙️ `with` 🍫, 👥 ⚒ 💭 👈 📁-💖 🎚 📪 ⏮️ 🚂 🔢 🔨. , ⏮️ ⚫️ 🏁 📨 📨.
+3️⃣. 👉 `yield from` 💬 🔢 🔁 🤭 👈 👜 🌟 `file_like`. & ⤴️, 🔠 🍕 🔁, 🌾 👈 🍕 👟 ⚪️➡️ 👉 🚂 🔢.
+
+ , ⚫️ 🚂 🔢 👈 📨 "🏭" 👷 🕳 🙆 🔘.
+
+ 🔨 ⚫️ 👉 🌌, 👥 💪 🚮 ⚫️ `with` 🍫, & 👈 🌌, 🚚 👈 ⚫️ 📪 ⏮️ 🏁.
+
+!!! tip
+ 👀 👈 📥 👥 ⚙️ 🐩 `open()` 👈 🚫 🐕🦺 `async` & `await`, 👥 📣 ➡ 🛠️ ⏮️ 😐 `def`.
+
+### `FileResponse`
+
+🔁 🎏 📁 📨.
+
+✊ 🎏 ⚒ ❌ 🔗 🌘 🎏 📨 🆎:
+
+* `path` - 📁 📁 🎏.
+* `headers` - 🙆 🛃 🎚 🔌, 📖.
+* `media_type` - 🎻 🤝 📻 🆎. 🚥 🔢, 📁 ⚖️ ➡ 🔜 ⚙️ 🔑 📻 🆎.
+* `filename` - 🚥 ⚒, 👉 🔜 🔌 📨 `Content-Disposition`.
+
+📁 📨 🔜 🔌 ☑ `Content-Length`, `Last-Modified` & `ETag` 🎚.
+
+```Python hl_lines="2 10"
+{!../../../docs_src/custom_response/tutorial009.py!}
+```
+
+👆 💪 ⚙️ `response_class` 🔢:
+
+```Python hl_lines="2 8 10"
+{!../../../docs_src/custom_response/tutorial009b.py!}
+```
+
+👉 💼, 👆 💪 📨 📁 ➡ 🔗 ⚪️➡️ 👆 *➡ 🛠️* 🔢.
+
+## 🛃 📨 🎓
+
+👆 💪 ✍ 👆 👍 🛃 📨 🎓, 😖 ⚪️➡️ `Response` & ⚙️ ⚫️.
+
+🖼, ➡️ 💬 👈 👆 💚 ⚙️ `orjson`, ✋️ ⏮️ 🛃 ⚒ 🚫 ⚙️ 🔌 `ORJSONResponse` 🎓.
+
+➡️ 💬 👆 💚 ⚫️ 📨 🔂 & 📁 🎻, 👆 💚 ⚙️ Orjson 🎛 `orjson.OPT_INDENT_2`.
+
+👆 💪 ✍ `CustomORJSONResponse`. 👑 👜 👆 ✔️ ✍ `Response.render(content)` 👩🔬 👈 📨 🎚 `bytes`:
+
+```Python hl_lines="9-14 17"
+{!../../../docs_src/custom_response/tutorial009c.py!}
+```
+
+🔜 ↩️ 🛬:
+
+```json
+{"message": "Hello World"}
+```
+
+...👉 📨 🔜 📨:
+
+```json
+{
+ "message": "Hello World"
+}
+```
+
+↗️, 👆 🔜 🎲 🔎 🌅 👍 🌌 ✊ 📈 👉 🌘 ❕ 🎻. 👶
+
+## 🔢 📨 🎓
+
+🕐❔ 🏗 **FastAPI** 🎓 👐 ⚖️ `APIRouter` 👆 💪 ✔ ❔ 📨 🎓 ⚙️ 🔢.
+
+🔢 👈 🔬 👉 `default_response_class`.
+
+🖼 🔛, **FastAPI** 🔜 ⚙️ `ORJSONResponse` 🔢, 🌐 *➡ 🛠️*, ↩️ `JSONResponse`.
+
+```Python hl_lines="2 4"
+{!../../../docs_src/custom_response/tutorial010.py!}
+```
+
+!!! tip
+ 👆 💪 🔐 `response_class` *➡ 🛠️* ⏭.
+
+## 🌖 🧾
+
+👆 💪 📣 📻 🆎 & 📚 🎏 ℹ 🗄 ⚙️ `responses`: [🌖 📨 🗄](additional-responses.md){.internal-link target=_blank}.
diff --git a/docs/em/docs/advanced/dataclasses.md b/docs/em/docs/advanced/dataclasses.md
new file mode 100644
index 000000000..a4c287106
--- /dev/null
+++ b/docs/em/docs/advanced/dataclasses.md
@@ -0,0 +1,98 @@
+# ⚙️ 🎻
+
+FastAPI 🏗 🔛 🔝 **Pydantic**, & 👤 ✔️ 🌏 👆 ❔ ⚙️ Pydantic 🏷 📣 📨 & 📨.
+
+✋️ FastAPI 🐕🦺 ⚙️ `dataclasses` 🎏 🌌:
+
+```Python hl_lines="1 7-12 19-20"
+{!../../../docs_src/dataclasses/tutorial001.py!}
+```
+
+👉 🐕🦺 👏 **Pydantic**, ⚫️ ✔️ 🔗 🐕🦺 `dataclasses`.
+
+, ⏮️ 📟 🔛 👈 🚫 ⚙️ Pydantic 🎯, FastAPI ⚙️ Pydantic 🗜 📚 🐩 🎻 Pydantic 👍 🍛 🎻.
+
+& ↗️, ⚫️ 🐕🦺 🎏:
+
+* 💽 🔬
+* 💽 🛠️
+* 💽 🧾, ♒️.
+
+👉 👷 🎏 🌌 ⏮️ Pydantic 🏷. & ⚫️ 🤙 🏆 🎏 🌌 🔘, ⚙️ Pydantic.
+
+!!! info
+ ✔️ 🤯 👈 🎻 💪 🚫 🌐 Pydantic 🏷 💪.
+
+ , 👆 5️⃣📆 💪 ⚙️ Pydantic 🏷.
+
+ ✋️ 🚥 👆 ✔️ 📚 🎻 🤥 🤭, 👉 👌 🎱 ⚙️ 👫 🏋️ 🕸 🛠️ ⚙️ FastAPI. 👶
+
+## 🎻 `response_model`
+
+👆 💪 ⚙️ `dataclasses` `response_model` 🔢:
+
+```Python hl_lines="1 7-13 19"
+{!../../../docs_src/dataclasses/tutorial002.py!}
+```
+
+🎻 🔜 🔁 🗜 Pydantic 🎻.
+
+👉 🌌, 🚮 🔗 🔜 🎦 🆙 🛠️ 🩺 👩💻 🔢:
+
+
+
+## 🎻 🔁 📊 📊
+
+👆 💪 🌀 `dataclasses` ⏮️ 🎏 🆎 ✍ ⚒ 🐦 📊 📊.
+
+💼, 👆 💪 ✔️ ⚙️ Pydantic ⏬ `dataclasses`. 🖼, 🚥 👆 ✔️ ❌ ⏮️ 🔁 🏗 🛠️ 🧾.
+
+👈 💼, 👆 💪 🎯 💱 🐩 `dataclasses` ⏮️ `pydantic.dataclasses`, ❔ 💧-♻:
+
+```{ .python .annotate hl_lines="1 5 8-11 14-17 23-25 28" }
+{!../../../docs_src/dataclasses/tutorial003.py!}
+```
+
+1️⃣. 👥 🗄 `field` ⚪️➡️ 🐩 `dataclasses`.
+
+2️⃣. `pydantic.dataclasses` 💧-♻ `dataclasses`.
+
+3️⃣. `Author` 🎻 🔌 📇 `Item` 🎻.
+
+4️⃣. `Author` 🎻 ⚙️ `response_model` 🔢.
+
+5️⃣. 👆 💪 ⚙️ 🎏 🐩 🆎 ✍ ⏮️ 🎻 📨 💪.
+
+ 👉 💼, ⚫️ 📇 `Item` 🎻.
+
+6️⃣. 📥 👥 🛬 📖 👈 🔌 `items` ❔ 📇 🎻.
+
+ FastAPI 🎯 ✍ 💽 🎻.
+
+7️⃣. 📥 `response_model` ⚙️ 🆎 ✍ 📇 `Author` 🎻.
+
+ 🔄, 👆 💪 🌀 `dataclasses` ⏮️ 🐩 🆎 ✍.
+
+8️⃣. 👀 👈 👉 *➡ 🛠️ 🔢* ⚙️ 🥔 `def` ↩️ `async def`.
+
+ 🕧, FastAPI 👆 💪 🌀 `def` & `async def` 💪.
+
+ 🚥 👆 💪 ↗️ 🔃 🕐❔ ⚙️ ❔, ✅ 👅 📄 _"🏃 ❓" _ 🩺 🔃 `async` & `await`.
+
+9️⃣. 👉 *➡ 🛠️ 🔢* 🚫 🛬 🎻 (👐 ⚫️ 💪), ✋️ 📇 📖 ⏮️ 🔗 💽.
+
+ FastAPI 🔜 ⚙️ `response_model` 🔢 (👈 🔌 🎻) 🗜 📨.
+
+👆 💪 🌀 `dataclasses` ⏮️ 🎏 🆎 ✍ 📚 🎏 🌀 📨 🏗 📊 📊.
+
+✅-📟 ✍ 💁♂ 🔛 👀 🌅 🎯 ℹ.
+
+## 💡 🌅
+
+👆 💪 🌀 `dataclasses` ⏮️ 🎏 Pydantic 🏷, 😖 ⚪️➡️ 👫, 🔌 👫 👆 👍 🏷, ♒️.
+
+💡 🌅, ✅ Pydantic 🩺 🔃 🎻.
+
+## ⏬
+
+👉 💪 ↩️ FastAPI ⏬ `0.67.0`. 👶
diff --git a/docs/em/docs/advanced/events.md b/docs/em/docs/advanced/events.md
new file mode 100644
index 000000000..671e81b18
--- /dev/null
+++ b/docs/em/docs/advanced/events.md
@@ -0,0 +1,160 @@
+# 🔆 🎉
+
+👆 💪 🔬 ⚛ (📟) 👈 🔜 🛠️ ⏭ 🈸 **▶️ 🆙**. 👉 ⛓ 👈 👉 📟 🔜 🛠️ **🕐**, **⏭** 🈸 **▶️ 📨 📨**.
+
+🎏 🌌, 👆 💪 🔬 ⚛ (📟) 👈 🔜 🛠️ 🕐❔ 🈸 **🤫 🔽**. 👉 💼, 👉 📟 🔜 🛠️ **🕐**, **⏮️** ✔️ 🍵 🎲 **📚 📨**.
+
+↩️ 👉 📟 🛠️ ⏭ 🈸 **▶️** ✊ 📨, & ▶️️ ⏮️ ⚫️ **🏁** 🚚 📨, ⚫️ 📔 🎂 🈸 **🔆** (🔤 "🔆" 🔜 ⚠ 🥈 👶).
+
+👉 💪 📶 ⚠ ⚒ 🆙 **ℹ** 👈 👆 💪 ⚙️ 🎂 📱, & 👈 **💰** 👪 📨, &/⚖️ 👈 👆 💪 **🧹 🆙** ⏮️. 🖼, 💽 🔗 🎱, ⚖️ 🚚 🔗 🎰 🏫 🏷.
+
+## ⚙️ 💼
+
+➡️ ▶️ ⏮️ 🖼 **⚙️ 💼** & ⤴️ 👀 ❔ ❎ ⚫️ ⏮️ 👉.
+
+➡️ 🌈 👈 👆 ✔️ **🎰 🏫 🏷** 👈 👆 💚 ⚙️ 🍵 📨. 👶
+
+🎏 🏷 🔗 👪 📨,, ⚫️ 🚫 1️⃣ 🏷 📍 📨, ⚖️ 1️⃣ 📍 👩💻 ⚖️ 🕳 🎏.
+
+➡️ 🌈 👈 🚚 🏷 💪 **✊ 🕰**, ↩️ ⚫️ ✔️ ✍ 📚 **💽 ⚪️➡️ 💾**. 👆 🚫 💚 ⚫️ 🔠 📨.
+
+👆 💪 📐 ⚫️ 🔝 🎚 🕹/📁, ✋️ 👈 🔜 ⛓ 👈 ⚫️ 🔜 **📐 🏷** 🚥 👆 🏃♂ 🙅 🏧 💯, ⤴️ 👈 💯 🔜 **🐌** ↩️ ⚫️ 🔜 ✔️ ⌛ 🏷 📐 ⏭ 💆♂ 💪 🏃 🔬 🍕 📟.
+
+👈 ⚫️❔ 👥 🔜 ❎, ➡️ 📐 🏷 ⏭ 📨 🍵, ✋️ 🕴 ▶️️ ⏭ 🈸 ▶️ 📨 📨, 🚫 ⏪ 📟 ➖ 📐.
+
+## 🔆
+
+👆 💪 🔬 👉 *🕴* & *🤫* ⚛ ⚙️ `lifespan` 🔢 `FastAPI` 📱, & "🔑 👨💼" (👤 🔜 🎦 👆 ⚫️❔ 👈 🥈).
+
+➡️ ▶️ ⏮️ 🖼 & ⤴️ 👀 ⚫️ ℹ.
+
+👥 ✍ 🔁 🔢 `lifespan()` ⏮️ `yield` 💖 👉:
+
+```Python hl_lines="16 19"
+{!../../../docs_src/events/tutorial003.py!}
+```
+
+📥 👥 ⚖ 😥 *🕴* 🛠️ 🚚 🏷 🚮 (❌) 🏷 🔢 📖 ⏮️ 🎰 🏫 🏷 ⏭ `yield`. 👉 📟 🔜 🛠️ **⏭** 🈸 **▶️ ✊ 📨**, ⏮️ *🕴*.
+
+& ⤴️, ▶️️ ⏮️ `yield`, 👥 🚚 🏷. 👉 📟 🔜 🛠️ **⏮️** 🈸 **🏁 🚚 📨**, ▶️️ ⏭ *🤫*. 👉 💪, 🖼, 🚀 ℹ 💖 💾 ⚖️ 💻.
+
+!!! tip
+ `shutdown` 🔜 🔨 🕐❔ 👆 **⛔️** 🈸.
+
+ 🎲 👆 💪 ▶️ 🆕 ⏬, ⚖️ 👆 🤚 🎡 🏃 ⚫️. 🤷
+
+### 🔆 🔢
+
+🥇 👜 👀, 👈 👥 ⚖ 🔁 🔢 ⏮️ `yield`. 👉 📶 🎏 🔗 ⏮️ `yield`.
+
+```Python hl_lines="14-19"
+{!../../../docs_src/events/tutorial003.py!}
+```
+
+🥇 🍕 🔢, ⏭ `yield`, 🔜 🛠️ **⏭** 🈸 ▶️.
+
+& 🍕 ⏮️ `yield` 🔜 🛠️ **⏮️** 🈸 ✔️ 🏁.
+
+### 🔁 🔑 👨💼
+
+🚥 👆 ✅, 🔢 🎀 ⏮️ `@asynccontextmanager`.
+
+👈 🗜 🔢 🔘 🕳 🤙 "**🔁 🔑 👨💼**".
+
+```Python hl_lines="1 13"
+{!../../../docs_src/events/tutorial003.py!}
+```
+
+**🔑 👨💼** 🐍 🕳 👈 👆 💪 ⚙️ `with` 📄, 🖼, `open()` 💪 ⚙️ 🔑 👨💼:
+
+```Python
+with open("file.txt") as file:
+ file.read()
+```
+
+⏮️ ⏬ 🐍, 📤 **🔁 🔑 👨💼**. 👆 🔜 ⚙️ ⚫️ ⏮️ `async with`:
+
+```Python
+async with lifespan(app):
+ await do_stuff()
+```
+
+🕐❔ 👆 ✍ 🔑 👨💼 ⚖️ 🔁 🔑 👨💼 💖 🔛, ⚫️❔ ⚫️ 🔨 👈, ⏭ 🛬 `with` 🍫, ⚫️ 🔜 🛠️ 📟 ⏭ `yield`, & ⏮️ ❎ `with` 🍫, ⚫️ 🔜 🛠️ 📟 ⏮️ `yield`.
+
+👆 📟 🖼 🔛, 👥 🚫 ⚙️ ⚫️ 🔗, ✋️ 👥 🚶♀️ ⚫️ FastAPI ⚫️ ⚙️ ⚫️.
+
+`lifespan` 🔢 `FastAPI` 📱 ✊ **🔁 🔑 👨💼**, 👥 💪 🚶♀️ 👆 🆕 `lifespan` 🔁 🔑 👨💼 ⚫️.
+
+```Python hl_lines="22"
+{!../../../docs_src/events/tutorial003.py!}
+```
+
+## 🎛 🎉 (😢)
+
+!!! warning
+ 👍 🌌 🍵 *🕴* & *🤫* ⚙️ `lifespan` 🔢 `FastAPI` 📱 🔬 🔛.
+
+ 👆 💪 🎲 🚶 👉 🍕.
+
+📤 🎛 🌌 🔬 👉 ⚛ 🛠️ ⏮️ *🕴* & ⏮️ *🤫*.
+
+👆 💪 🔬 🎉 🐕🦺 (🔢) 👈 💪 🛠️ ⏭ 🈸 ▶️ 🆙, ⚖️ 🕐❔ 🈸 🤫 🔽.
+
+👫 🔢 💪 📣 ⏮️ `async def` ⚖️ 😐 `def`.
+
+### `startup` 🎉
+
+🚮 🔢 👈 🔜 🏃 ⏭ 🈸 ▶️, 📣 ⚫️ ⏮️ 🎉 `"startup"`:
+
+```Python hl_lines="8"
+{!../../../docs_src/events/tutorial001.py!}
+```
+
+👉 💼, `startup` 🎉 🐕🦺 🔢 🔜 🔢 🏬 "💽" ( `dict`) ⏮️ 💲.
+
+👆 💪 🚮 🌅 🌘 1️⃣ 🎉 🐕🦺 🔢.
+
+& 👆 🈸 🏆 🚫 ▶️ 📨 📨 ⏭ 🌐 `startup` 🎉 🐕🦺 ✔️ 🏁.
+
+### `shutdown` 🎉
+
+🚮 🔢 👈 🔜 🏃 🕐❔ 🈸 🤫 🔽, 📣 ⚫️ ⏮️ 🎉 `"shutdown"`:
+
+```Python hl_lines="6"
+{!../../../docs_src/events/tutorial002.py!}
+```
+
+📥, `shutdown` 🎉 🐕🦺 🔢 🔜 ✍ ✍ ⏸ `"Application shutdown"` 📁 `log.txt`.
+
+!!! info
+ `open()` 🔢, `mode="a"` ⛓ "🎻",, ⏸ 🔜 🚮 ⏮️ ⚫️❔ 🔛 👈 📁, 🍵 📁 ⏮️ 🎚.
+
+!!! tip
+ 👀 👈 👉 💼 👥 ⚙️ 🐩 🐍 `open()` 🔢 👈 🔗 ⏮️ 📁.
+
+ , ⚫️ 🔌 👤/🅾 (🔢/🔢), 👈 🚚 "⌛" 👜 ✍ 💾.
+
+ ✋️ `open()` 🚫 ⚙️ `async` & `await`.
+
+ , 👥 📣 🎉 🐕🦺 🔢 ⏮️ 🐩 `def` ↩️ `async def`.
+
+!!! info
+ 👆 💪 ✍ 🌅 🔃 👫 🎉 🐕🦺 💃 🎉' 🩺.
+
+### `startup` & `shutdown` 👯♂️
+
+📤 ↕ 🤞 👈 ⚛ 👆 *🕴* & *🤫* 🔗, 👆 💪 💚 ▶️ 🕳 & ⤴️ 🏁 ⚫️, 📎 ℹ & ⤴️ 🚀 ⚫️, ♒️.
+
+🔨 👈 👽 🔢 👈 🚫 💰 ⚛ ⚖️ 🔢 👯♂️ 🌅 ⚠ 👆 🔜 💪 🏪 💲 🌐 🔢 ⚖️ 🎏 🎱.
+
+↩️ 👈, ⚫️ 🔜 👍 ↩️ ⚙️ `lifespan` 🔬 🔛.
+
+## 📡 ℹ
+
+📡 ℹ 😟 🤓. 👶
+
+🔘, 🔫 📡 🔧, 👉 🍕 🔆 🛠️, & ⚫️ 🔬 🎉 🤙 `startup` & `shutdown`.
+
+## 🎧 🈸
+
+👶 ✔️ 🤯 👈 👫 🔆 🎉 (🕴 & 🤫) 🔜 🕴 🛠️ 👑 🈸, 🚫 [🎧 🈸 - 🗻](./sub-applications.md){.internal-link target=_blank}.
diff --git a/docs/em/docs/advanced/extending-openapi.md b/docs/em/docs/advanced/extending-openapi.md
new file mode 100644
index 000000000..496a8d9de
--- /dev/null
+++ b/docs/em/docs/advanced/extending-openapi.md
@@ -0,0 +1,314 @@
+# ↔ 🗄
+
+!!! warning
+ 👉 👍 🏧 ⚒. 👆 🎲 💪 🚶 ⚫️.
+
+ 🚥 👆 📄 🔰 - 👩💻 🦮, 👆 💪 🎲 🚶 👉 📄.
+
+ 🚥 👆 ⏪ 💭 👈 👆 💪 🔀 🏗 🗄 🔗, 😣 👂.
+
+📤 💼 🌐❔ 👆 💪 💪 🔀 🏗 🗄 🔗.
+
+👉 📄 👆 🔜 👀 ❔.
+
+## 😐 🛠️
+
+😐 (🔢) 🛠️, ⏩.
+
+`FastAPI` 🈸 (👐) ✔️ `.openapi()` 👩🔬 👈 📈 📨 🗄 🔗.
+
+🍕 🈸 🎚 🏗, *➡ 🛠️* `/openapi.json` (⚖️ ⚫️❔ 👆 ⚒ 👆 `openapi_url`) ®.
+
+⚫️ 📨 🎻 📨 ⏮️ 🏁 🈸 `.openapi()` 👩🔬.
+
+🔢, ⚫️❔ 👩🔬 `.openapi()` 🔨 ✅ 🏠 `.openapi_schema` 👀 🚥 ⚫️ ✔️ 🎚 & 📨 👫.
+
+🚥 ⚫️ 🚫, ⚫️ 🏗 👫 ⚙️ 🚙 🔢 `fastapi.openapi.utils.get_openapi`.
+
+& 👈 🔢 `get_openapi()` 📨 🔢:
+
+* `title`: 🗄 📛, 🎦 🩺.
+* `version`: ⏬ 👆 🛠️, ✅ `2.5.0`.
+* `openapi_version`: ⏬ 🗄 🔧 ⚙️. 🔢, ⏪: `3.0.2`.
+* `description`: 📛 👆 🛠️.
+* `routes`: 📇 🛣, 👫 🔠 ® *➡ 🛠️*. 👫 ✊ ⚪️➡️ `app.routes`.
+
+## 🔑 🔢
+
+⚙️ ℹ 🔛, 👆 💪 ⚙️ 🎏 🚙 🔢 🏗 🗄 🔗 & 🔐 🔠 🍕 👈 👆 💪.
+
+🖼, ➡️ 🚮 📄 🗄 ↔ 🔌 🛃 🔱.
+
+### 😐 **FastAPI**
+
+🥇, ✍ 🌐 👆 **FastAPI** 🈸 🛎:
+
+```Python hl_lines="1 4 7-9"
+{!../../../docs_src/extending_openapi/tutorial001.py!}
+```
+
+### 🏗 🗄 🔗
+
+⤴️, ⚙️ 🎏 🚙 🔢 🏗 🗄 🔗, 🔘 `custom_openapi()` 🔢:
+
+```Python hl_lines="2 15-20"
+{!../../../docs_src/extending_openapi/tutorial001.py!}
+```
+
+### 🔀 🗄 🔗
+
+🔜 👆 💪 🚮 📄 ↔, ❎ 🛃 `x-logo` `info` "🎚" 🗄 🔗:
+
+```Python hl_lines="21-23"
+{!../../../docs_src/extending_openapi/tutorial001.py!}
+```
+
+### 💾 🗄 🔗
+
+👆 💪 ⚙️ 🏠 `.openapi_schema` "💾", 🏪 👆 🏗 🔗.
+
+👈 🌌, 👆 🈸 🏆 🚫 ✔️ 🏗 🔗 🔠 🕰 👩💻 📂 👆 🛠️ 🩺.
+
+⚫️ 🔜 🏗 🕴 🕐, & ⤴️ 🎏 💾 🔗 🔜 ⚙️ ⏭ 📨.
+
+```Python hl_lines="13-14 24-25"
+{!../../../docs_src/extending_openapi/tutorial001.py!}
+```
+
+### 🔐 👩🔬
+
+🔜 👆 💪 ❎ `.openapi()` 👩🔬 ⏮️ 👆 🆕 🔢.
+
+```Python hl_lines="28"
+{!../../../docs_src/extending_openapi/tutorial001.py!}
+```
+
+### ✅ ⚫️
+
+🕐 👆 🚶 http://127.0.0.1:8000/redoc 👆 🔜 👀 👈 👆 ⚙️ 👆 🛃 🔱 (👉 🖼, **FastAPI**'Ⓜ 🔱):
+
+
+
+## 👤-🕸 🕸 & 🎚 🩺
+
+🛠️ 🩺 ⚙️ **🦁 🎚** & **📄**, & 🔠 👈 💪 🕸 & 🎚 📁.
+
+🔢, 👈 📁 🍦 ⚪️➡️ 💲.
+
+✋️ ⚫️ 💪 🛃 ⚫️, 👆 💪 ⚒ 🎯 💲, ⚖️ 🍦 📁 👆.
+
+👈 ⚠, 🖼, 🚥 👆 💪 👆 📱 🚧 👷 ⏪ 📱, 🍵 📂 🕸 🔐, ⚖️ 🇧🇿 🕸.
+
+📥 👆 🔜 👀 ❔ 🍦 👈 📁 👆, 🎏 FastAPI 📱, & 🔗 🩺 ⚙️ 👫.
+
+### 🏗 📁 📊
+
+➡️ 💬 👆 🏗 📁 📊 👀 💖 👉:
+
+```
+.
+├── app
+│ ├── __init__.py
+│ ├── main.py
+```
+
+🔜 ✍ 📁 🏪 📚 🎻 📁.
+
+👆 🆕 📁 📊 💪 👀 💖 👉:
+
+```
+.
+├── app
+│ ├── __init__.py
+│ ├── main.py
+└── static/
+```
+
+### ⏬ 📁
+
+⏬ 🎻 📁 💪 🩺 & 🚮 👫 🔛 👈 `static/` 📁.
+
+👆 💪 🎲 ▶️️-🖊 🔠 🔗 & 🖊 🎛 🎏 `Save link as...`.
+
+**🦁 🎚** ⚙️ 📁:
+
+* `swagger-ui-bundle.js`
+* `swagger-ui.css`
+
+& **📄** ⚙️ 📁:
+
+* `redoc.standalone.js`
+
+⏮️ 👈, 👆 📁 📊 💪 👀 💖:
+
+```
+.
+├── app
+│ ├── __init__.py
+│ ├── main.py
+└── static
+ ├── redoc.standalone.js
+ ├── swagger-ui-bundle.js
+ └── swagger-ui.css
+```
+
+### 🍦 🎻 📁
+
+* 🗄 `StaticFiles`.
+* "🗻" `StaticFiles()` 👐 🎯 ➡.
+
+```Python hl_lines="7 11"
+{!../../../docs_src/extending_openapi/tutorial002.py!}
+```
+
+### 💯 🎻 📁
+
+▶️ 👆 🈸 & 🚶 http://127.0.0.1:8000/static/redoc.standalone.js.
+
+👆 🔜 👀 📶 📏 🕸 📁 **📄**.
+
+⚫️ 💪 ▶️ ⏮️ 🕳 💖:
+
+```JavaScript
+/*!
+ * ReDoc - OpenAPI/Swagger-generated API Reference Documentation
+ * -------------------------------------------------------------
+ * Version: "2.0.0-rc.18"
+ * Repo: https://github.com/Redocly/redoc
+ */
+!function(e,t){"object"==typeof exports&&"object"==typeof m
+
+...
+```
+
+👈 ✔ 👈 👆 💆♂ 💪 🍦 🎻 📁 ⚪️➡️ 👆 📱, & 👈 👆 🥉 🎻 📁 🩺 ☑ 🥉.
+
+🔜 👥 💪 🔗 📱 ⚙️ 📚 🎻 📁 🩺.
+
+### ❎ 🏧 🩺
+
+🥇 🔁 ❎ 🏧 🩺, 📚 ⚙️ 💲 🔢.
+
+❎ 👫, ⚒ 👫 📛 `None` 🕐❔ 🏗 👆 `FastAPI` 📱:
+
+```Python hl_lines="9"
+{!../../../docs_src/extending_openapi/tutorial002.py!}
+```
+
+### 🔌 🛃 🩺
+
+🔜 👆 💪 ✍ *➡ 🛠️* 🛃 🩺.
+
+👆 💪 🏤-⚙️ FastAPI 🔗 🔢 ✍ 🕸 📃 🩺, & 🚶♀️ 👫 💪 ❌:
+
+* `openapi_url`: 📛 🌐❔ 🕸 📃 🩺 💪 🤚 🗄 🔗 👆 🛠️. 👆 💪 ⚙️ 📥 🔢 `app.openapi_url`.
+* `title`: 📛 👆 🛠️.
+* `oauth2_redirect_url`: 👆 💪 ⚙️ `app.swagger_ui_oauth2_redirect_url` 📥 ⚙️ 🔢.
+* `swagger_js_url`: 📛 🌐❔ 🕸 👆 🦁 🎚 🩺 💪 🤚 **🕸** 📁. 👉 1️⃣ 👈 👆 👍 📱 🔜 🍦.
+* `swagger_css_url`: 📛 🌐❔ 🕸 👆 🦁 🎚 🩺 💪 🤚 **🎚** 📁. 👉 1️⃣ 👈 👆 👍 📱 🔜 🍦.
+
+& ➡ 📄...
+
+```Python hl_lines="2-6 14-22 25-27 30-36"
+{!../../../docs_src/extending_openapi/tutorial002.py!}
+```
+
+!!! tip
+ *➡ 🛠️* `swagger_ui_redirect` 👩🎓 🕐❔ 👆 ⚙️ Oauth2️⃣.
+
+ 🚥 👆 🛠️ 👆 🛠️ ⏮️ Oauth2️⃣ 🐕🦺, 👆 🔜 💪 🔓 & 👟 🔙 🛠️ 🩺 ⏮️ 📎 🎓. & 🔗 ⏮️ ⚫️ ⚙️ 🎰 Oauth2️⃣ 🤝.
+
+ 🦁 🎚 🔜 🍵 ⚫️ ⛅ 🎑 👆, ✋️ ⚫️ 💪 👉 "❎" 👩🎓.
+
+### ✍ *➡ 🛠️* 💯 ⚫️
+
+🔜, 💪 💯 👈 🌐 👷, ✍ *➡ 🛠️*:
+
+```Python hl_lines="39-41"
+{!../../../docs_src/extending_openapi/tutorial002.py!}
+```
+
+### 💯 ⚫️
+
+🔜, 👆 🔜 💪 🔌 👆 📻, 🚶 👆 🩺 http://127.0.0.1:8000/docs, & 🔃 📃.
+
+& 🍵 🕸, 👆 🔜 💪 👀 🩺 👆 🛠️ & 🔗 ⏮️ ⚫️.
+
+## 🛠️ 🦁 🎚
+
+👆 💪 🔗 ➕ 🦁 🎚 🔢.
+
+🔗 👫, 🚶♀️ `swagger_ui_parameters` ❌ 🕐❔ 🏗 `FastAPI()` 📱 🎚 ⚖️ `get_swagger_ui_html()` 🔢.
+
+`swagger_ui_parameters` 📨 📖 ⏮️ 📳 🚶♀️ 🦁 🎚 🔗.
+
+FastAPI 🗜 📳 **🎻** ⚒ 👫 🔗 ⏮️ 🕸, 👈 ⚫️❔ 🦁 🎚 💪.
+
+### ❎ ❕ 🎦
+
+🖼, 👆 💪 ❎ ❕ 🎦 🦁 🎚.
+
+🍵 🔀 ⚒, ❕ 🎦 🛠️ 🔢:
+
+
+
+✋️ 👆 💪 ❎ ⚫️ ⚒ `syntaxHighlight` `False`:
+
+```Python hl_lines="3"
+{!../../../docs_src/extending_openapi/tutorial003.py!}
+```
+
+...& ⤴️ 🦁 🎚 🏆 🚫 🎦 ❕ 🎦 🚫🔜:
+
+
+
+### 🔀 🎢
+
+🎏 🌌 👆 💪 ⚒ ❕ 🎦 🎢 ⏮️ 🔑 `"syntaxHighlight.theme"` (👀 👈 ⚫️ ✔️ ❣ 🖕):
+
+```Python hl_lines="3"
+{!../../../docs_src/extending_openapi/tutorial004.py!}
+```
+
+👈 📳 🔜 🔀 ❕ 🎦 🎨 🎢:
+
+
+
+### 🔀 🔢 🦁 🎚 🔢
+
+FastAPI 🔌 🔢 📳 🔢 ☑ 🌅 ⚙️ 💼.
+
+⚫️ 🔌 👫 🔢 📳:
+
+```Python
+{!../../../fastapi/openapi/docs.py[ln:7-13]!}
+```
+
+👆 💪 🔐 🙆 👫 ⚒ 🎏 💲 ❌ `swagger_ui_parameters`.
+
+🖼, ❎ `deepLinking` 👆 💪 🚶♀️ 👉 ⚒ `swagger_ui_parameters`:
+
+```Python hl_lines="3"
+{!../../../docs_src/extending_openapi/tutorial005.py!}
+```
+
+### 🎏 🦁 🎚 🔢
+
+👀 🌐 🎏 💪 📳 👆 💪 ⚙️, ✍ 🛂 🩺 🦁 🎚 🔢.
+
+### 🕸-🕴 ⚒
+
+🦁 🎚 ✔ 🎏 📳 **🕸-🕴** 🎚 (🖼, 🕸 🔢).
+
+FastAPI 🔌 👫 🕸-🕴 `presets` ⚒:
+
+```JavaScript
+presets: [
+ SwaggerUIBundle.presets.apis,
+ SwaggerUIBundle.SwaggerUIStandalonePreset
+]
+```
+
+👫 **🕸** 🎚, 🚫 🎻, 👆 💪 🚫 🚶♀️ 👫 ⚪️➡️ 🐍 📟 🔗.
+
+🚥 👆 💪 ⚙️ 🕸-🕴 📳 💖 📚, 👆 💪 ⚙️ 1️⃣ 👩🔬 🔛. 🔐 🌐 🦁 🎚 *➡ 🛠️* & ❎ ✍ 🙆 🕸 👆 💪.
diff --git a/docs/em/docs/advanced/generate-clients.md b/docs/em/docs/advanced/generate-clients.md
new file mode 100644
index 000000000..30560c8c6
--- /dev/null
+++ b/docs/em/docs/advanced/generate-clients.md
@@ -0,0 +1,267 @@
+# 🏗 👩💻
+
+**FastAPI** ⚓️ 🔛 🗄 🔧, 👆 🤚 🏧 🔗 ⏮️ 📚 🧰, 🔌 🏧 🛠️ 🩺 (🚚 🦁 🎚).
+
+1️⃣ 🎯 📈 👈 🚫 🎯 ⭐ 👈 👆 💪 **🏗 👩💻** (🕣 🤙 **📱** ) 👆 🛠️, 📚 🎏 **🛠️ 🇪🇸**.
+
+## 🗄 👩💻 🚂
+
+📤 📚 🧰 🏗 👩💻 ⚪️➡️ **🗄**.
+
+⚠ 🧰 🗄 🚂.
+
+🚥 👆 🏗 **🕸**, 📶 😌 🎛 🗄-📕-🇦🇪.
+
+## 🏗 📕 🕸 👩💻
+
+➡️ ▶️ ⏮️ 🙅 FastAPI 🈸:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9-11 14-15 18 19 23"
+ {!> ../../../docs_src/generate_clients/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="7-9 12-13 16-17 21"
+ {!> ../../../docs_src/generate_clients/tutorial001_py39.py!}
+ ```
+
+👀 👈 *➡ 🛠️* 🔬 🏷 👫 ⚙️ 📨 🚀 & 📨 🚀, ⚙️ 🏷 `Item` & `ResponseMessage`.
+
+### 🛠️ 🩺
+
+🚥 👆 🚶 🛠️ 🩺, 👆 🔜 👀 👈 ⚫️ ✔️ **🔗** 📊 📨 📨 & 📨 📨:
+
+
+
+👆 💪 👀 👈 🔗 ↩️ 👫 📣 ⏮️ 🏷 📱.
+
+👈 ℹ 💪 📱 **🗄 🔗**, & ⤴️ 🎦 🛠️ 🩺 (🦁 🎚).
+
+& 👈 🎏 ℹ ⚪️➡️ 🏷 👈 🔌 🗄 ⚫️❔ 💪 ⚙️ **🏗 👩💻 📟**.
+
+### 🏗 📕 👩💻
+
+🔜 👈 👥 ✔️ 📱 ⏮️ 🏷, 👥 💪 🏗 👩💻 📟 🕸.
+
+#### ❎ `openapi-typescript-codegen`
+
+👆 💪 ❎ `openapi-typescript-codegen` 👆 🕸 📟 ⏮️:
+
+
+
+👆 🔜 🤚 ✍ 🚀 📨:
+
+
+
+!!! tip
+ 👀 ✍ `name` & `price`, 👈 🔬 FastAPI 🈸, `Item` 🏷.
+
+👆 🔜 ✔️ ⏸ ❌ 📊 👈 👆 📨:
+
+
+
+📨 🎚 🔜 ✔️ ✍:
+
+
+
+## FastAPI 📱 ⏮️ 🔖
+
+📚 💼 👆 FastAPI 📱 🔜 🦏, & 👆 🔜 🎲 ⚙️ 🔖 🎏 🎏 👪 *➡ 🛠️*.
+
+🖼, 👆 💪 ✔️ 📄 **🏬** & ➕1️⃣ 📄 **👩💻**, & 👫 💪 👽 🔖:
+
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="23 28 36"
+ {!> ../../../docs_src/generate_clients/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="21 26 34"
+ {!> ../../../docs_src/generate_clients/tutorial002_py39.py!}
+ ```
+
+### 🏗 📕 👩💻 ⏮️ 🔖
+
+🚥 👆 🏗 👩💻 FastAPI 📱 ⚙️ 🔖, ⚫️ 🔜 🛎 🎏 👩💻 📟 ⚓️ 🔛 🔖.
+
+👉 🌌 👆 🔜 💪 ✔️ 👜 ✔ & 👪 ☑ 👩💻 📟:
+
+
+
+👉 💼 👆 ✔️:
+
+* `ItemsService`
+* `UsersService`
+
+### 👩💻 👩🔬 📛
+
+▶️️ 🔜 🏗 👩🔬 📛 💖 `createItemItemsPost` 🚫 👀 📶 🧹:
+
+```TypeScript
+ItemsService.createItemItemsPost({name: "Plumbus", price: 5})
+```
+
+...👈 ↩️ 👩💻 🚂 ⚙️ 🗄 🔗 **🛠️ 🆔** 🔠 *➡ 🛠️*.
+
+🗄 🚚 👈 🔠 🛠️ 🆔 😍 🤭 🌐 *➡ 🛠️*, FastAPI ⚙️ **🔢 📛**, **➡**, & **🇺🇸🔍 👩🔬/🛠️** 🏗 👈 🛠️ 🆔, ↩️ 👈 🌌 ⚫️ 💪 ⚒ 💭 👈 🛠️ 🆔 😍.
+
+✋️ 👤 🔜 🎦 👆 ❔ 📉 👈 ⏭. 👶
+
+## 🛃 🛠️ 🆔 & 👍 👩🔬 📛
+
+👆 💪 **🔀** 🌌 👫 🛠️ 🆔 **🏗** ⚒ 👫 🙅 & ✔️ **🙅 👩🔬 📛** 👩💻.
+
+👉 💼 👆 🔜 ✔️ 🚚 👈 🔠 🛠️ 🆔 **😍** 🎏 🌌.
+
+🖼, 👆 💪 ⚒ 💭 👈 🔠 *➡ 🛠️* ✔️ 🔖, & ⤴️ 🏗 🛠️ 🆔 ⚓️ 🔛 **🔖** & *➡ 🛠️* **📛** (🔢 📛).
+
+### 🛃 🏗 😍 🆔 🔢
+
+FastAPI ⚙️ **😍 🆔** 🔠 *➡ 🛠️*, ⚫️ ⚙️ **🛠️ 🆔** & 📛 🙆 💪 🛃 🏷, 📨 ⚖️ 📨.
+
+👆 💪 🛃 👈 🔢. ⚫️ ✊ `APIRoute` & 🔢 🎻.
+
+🖼, 📥 ⚫️ ⚙️ 🥇 🔖 (👆 🔜 🎲 ✔️ 🕴 1️⃣ 🔖) & *➡ 🛠️* 📛 (🔢 📛).
+
+👆 💪 ⤴️ 🚶♀️ 👈 🛃 🔢 **FastAPI** `generate_unique_id_function` 🔢:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="8-9 12"
+ {!> ../../../docs_src/generate_clients/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="6-7 10"
+ {!> ../../../docs_src/generate_clients/tutorial003_py39.py!}
+ ```
+
+### 🏗 📕 👩💻 ⏮️ 🛃 🛠️ 🆔
+
+🔜 🚥 👆 🏗 👩💻 🔄, 👆 🔜 👀 👈 ⚫️ ✔️ 📉 👩🔬 📛:
+
+
+
+👆 👀, 👩🔬 📛 🔜 ✔️ 🔖 & ⤴️ 🔢 📛, 🔜 👫 🚫 🔌 ℹ ⚪️➡️ 📛 ➡ & 🇺🇸🔍 🛠️.
+
+### 🗜 🗄 🔧 👩💻 🚂
+
+🏗 📟 ✔️ **❎ ℹ**.
+
+👥 ⏪ 💭 👈 👉 👩🔬 🔗 **🏬** ↩️ 👈 🔤 `ItemsService` (✊ ⚪️➡️ 🔖), ✋️ 👥 ✔️ 📛 🔡 👩🔬 📛 💁♂️. 👶
+
+👥 🔜 🎲 💚 🚧 ⚫️ 🗄 🏢, 👈 🔜 🚚 👈 🛠️ 🆔 **😍**.
+
+✋️ 🏗 👩💻 👥 💪 **🔀** 🗄 🛠️ 🆔 ▶️️ ⏭ 🏭 👩💻, ⚒ 👈 👩🔬 📛 👌 & **🧹**.
+
+👥 💪 ⏬ 🗄 🎻 📁 `openapi.json` & ⤴️ 👥 💪 **❎ 👈 🔡 🔖** ⏮️ ✍ 💖 👉:
+
+```Python
+{!../../../docs_src/generate_clients/tutorial004.py!}
+```
+
+⏮️ 👈, 🛠️ 🆔 🔜 📁 ⚪️➡️ 👜 💖 `items-get_items` `get_items`, 👈 🌌 👩💻 🚂 💪 🏗 🙅 👩🔬 📛.
+
+### 🏗 📕 👩💻 ⏮️ 🗜 🗄
+
+🔜 🔚 🏁 📁 `openapi.json`, 👆 🔜 🔀 `package.json` ⚙️ 👈 🇧🇿 📁, 🖼:
+
+```JSON hl_lines="7"
+{
+ "name": "frontend-app",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "generate-client": "openapi --input ./openapi.json --output ./src/client --client axios"
+ },
+ "author": "",
+ "license": "",
+ "devDependencies": {
+ "openapi-typescript-codegen": "^0.20.1",
+ "typescript": "^4.6.2"
+ }
+}
+```
+
+⏮️ 🏭 🆕 👩💻, 👆 🔜 🔜 ✔️ **🧹 👩🔬 📛**, ⏮️ 🌐 **✍**, **⏸ ❌**, ♒️:
+
+
+
+## 💰
+
+🕐❔ ⚙️ 🔁 🏗 👩💻 👆 🔜 **✍** :
+
+* 👩🔬.
+* 📨 🚀 💪, 🔢 🔢, ♒️.
+* 📨 🚀.
+
+👆 🔜 ✔️ **⏸ ❌** 🌐.
+
+& 🕐❔ 👆 ℹ 👩💻 📟, & **♻** 🕸, ⚫️ 🔜 ✔️ 🙆 🆕 *➡ 🛠️* 💪 👩🔬, 🗝 🕐 ❎, & 🙆 🎏 🔀 🔜 🎨 🔛 🏗 📟. 👶
+
+👉 ⛓ 👈 🚥 🕳 🔀 ⚫️ 🔜 **🎨** 🔛 👩💻 📟 🔁. & 🚥 👆 **🏗** 👩💻 ⚫️ 🔜 ❌ 👅 🚥 👆 ✔️ 🙆 **🔖** 📊 ⚙️.
+
+, 👆 🔜 **🔍 📚 ❌** 📶 ⏪ 🛠️ 🛵 ↩️ ✔️ ⌛ ❌ 🎦 🆙 👆 🏁 👩💻 🏭 & ⤴️ 🔄 ℹ 🌐❔ ⚠. 👶
diff --git a/docs/em/docs/advanced/graphql.md b/docs/em/docs/advanced/graphql.md
new file mode 100644
index 000000000..8509643ce
--- /dev/null
+++ b/docs/em/docs/advanced/graphql.md
@@ -0,0 +1,56 @@
+# 🕹
+
+**FastAPI** ⚓️ 🔛 **🔫** 🐩, ⚫️ 📶 ⏩ 🛠️ 🙆 **🕹** 🗃 🔗 ⏮️ 🔫.
+
+👆 💪 🌀 😐 FastAPI *➡ 🛠️* ⏮️ 🕹 🔛 🎏 🈸.
+
+!!! tip
+ **🕹** ❎ 📶 🎯 ⚙️ 💼.
+
+ ⚫️ ✔️ **📈** & **⚠** 🕐❔ 🔬 ⚠ **🕸 🔗**.
+
+ ⚒ 💭 👆 🔬 🚥 **💰** 👆 ⚙️ 💼 ⚖ **👐**. 👶
+
+## 🕹 🗃
+
+📥 **🕹** 🗃 👈 ✔️ **🔫** 🐕🦺. 👆 💪 ⚙️ 👫 ⏮️ **FastAPI**:
+
+* 🍓 👶
+ * ⏮️ 🩺 FastAPI
+* 👸
+ * ⏮️ 🩺 💃 (👈 ✔ FastAPI)
+* 🍟
+ * ⏮️ 🍟 🔫 🚚 🔫 🛠️
+* ⚗
+ * ⏮️ 💃-Graphene3️⃣
+
+## 🕹 ⏮️ 🍓
+
+🚥 👆 💪 ⚖️ 💚 👷 ⏮️ **🕹**, **🍓** **👍** 🗃 ⚫️ ✔️ 🔧 🔐 **FastAPI** 🔧, ⚫️ 🌐 ⚓️ 🔛 **🆎 ✍**.
+
+⚓️ 🔛 👆 ⚙️ 💼, 👆 5️⃣📆 💖 ⚙️ 🎏 🗃, ✋️ 🚥 👆 💭 👤, 👤 🔜 🎲 🤔 👆 🔄 **🍓**.
+
+📥 🤪 🎮 ❔ 👆 💪 🛠️ 🍓 ⏮️ FastAPI:
+
+```Python hl_lines="3 22 25-26"
+{!../../../docs_src/graphql/tutorial001.py!}
+```
+
+👆 💪 💡 🌅 🔃 🍓 🍓 🧾.
+
+& 🩺 🔃 🍓 ⏮️ FastAPI.
+
+## 🗝 `GraphQLApp` ⚪️➡️ 💃
+
+⏮️ ⏬ 💃 🔌 `GraphQLApp` 🎓 🛠️ ⏮️ ⚗.
+
+⚫️ 😢 ⚪️➡️ 💃, ✋️ 🚥 👆 ✔️ 📟 👈 ⚙️ ⚫️, 👆 💪 💪 **↔** 💃-Graphene3️⃣, 👈 📔 🎏 ⚙️ 💼 & ✔️ **🌖 🌓 🔢**.
+
+!!! tip
+ 🚥 👆 💪 🕹, 👤 🔜 👍 👆 ✅ 👅 🍓, ⚫️ ⚓️ 🔛 🆎 ✍ ↩️ 🛃 🎓 & 🆎.
+
+## 💡 🌅
+
+👆 💪 💡 🌅 🔃 **🕹** 🛂 🕹 🧾.
+
+👆 💪 ✍ 🌅 🔃 🔠 👈 🗃 🔬 🔛 👫 🔗.
diff --git a/docs/em/docs/advanced/index.md b/docs/em/docs/advanced/index.md
new file mode 100644
index 000000000..6a43a09e7
--- /dev/null
+++ b/docs/em/docs/advanced/index.md
@@ -0,0 +1,24 @@
+# 🏧 👩💻 🦮 - 🎶
+
+## 🌖 ⚒
+
+👑 [🔰 - 👩💻 🦮](../tutorial/){.internal-link target=_blank} 🔜 🥃 🤝 👆 🎫 🔘 🌐 👑 ⚒ **FastAPI**.
+
+⏭ 📄 👆 🔜 👀 🎏 🎛, 📳, & 🌖 ⚒.
+
+!!! tip
+ ⏭ 📄 **🚫 🎯 "🏧"**.
+
+ & ⚫️ 💪 👈 👆 ⚙️ 💼, ⚗ 1️⃣ 👫.
+
+## ✍ 🔰 🥇
+
+👆 💪 ⚙️ 🏆 ⚒ **FastAPI** ⏮️ 💡 ⚪️➡️ 👑 [🔰 - 👩💻 🦮](../tutorial/){.internal-link target=_blank}.
+
+& ⏭ 📄 🤔 👆 ⏪ ✍ ⚫️, & 🤔 👈 👆 💭 👈 👑 💭.
+
+## 🏎.🅾 ↗️
+
+🚥 👆 🔜 💖 ✊ 🏧-🔰 ↗️ 🔗 👉 📄 🩺, 👆 💪 💚 ✅: 💯-💾 🛠️ ⏮️ FastAPI & ☁ **🏎.🅾**.
+
+👫 ⏳ 🩸 1️⃣0️⃣ 💯 🌐 💰 🛠️ **FastAPI**. 👶 👶
diff --git a/docs/em/docs/advanced/middleware.md b/docs/em/docs/advanced/middleware.md
new file mode 100644
index 000000000..b3e722ed0
--- /dev/null
+++ b/docs/em/docs/advanced/middleware.md
@@ -0,0 +1,99 @@
+# 🏧 🛠️
+
+👑 🔰 👆 ✍ ❔ 🚮 [🛃 🛠️](../tutorial/middleware.md){.internal-link target=_blank} 👆 🈸.
+
+& ⤴️ 👆 ✍ ❔ 🍵 [⚜ ⏮️ `CORSMiddleware`](../tutorial/cors.md){.internal-link target=_blank}.
+
+👉 📄 👥 🔜 👀 ❔ ⚙️ 🎏 🛠️.
+
+## ❎ 🔫 🛠️
+
+**FastAPI** ⚓️ 🔛 💃 & 🛠️ 🔫 🔧, 👆 💪 ⚙️ 🙆 🔫 🛠️.
+
+🛠️ 🚫 ✔️ ⚒ FastAPI ⚖️ 💃 👷, 📏 ⚫️ ⏩ 🔫 🔌.
+
+🏢, 🔫 🛠️ 🎓 👈 ⌛ 📨 🔫 📱 🥇 ❌.
+
+, 🧾 🥉-🥳 🔫 🛠️ 👫 🔜 🎲 💬 👆 🕳 💖:
+
+```Python
+from unicorn import UnicornMiddleware
+
+app = SomeASGIApp()
+
+new_app = UnicornMiddleware(app, some_config="rainbow")
+```
+
+✋️ FastAPI (🤙 💃) 🚚 🙅 🌌 ⚫️ 👈 ⚒ 💭 👈 🔗 🛠️ 🍵 💽 ❌ & 🛃 ⚠ 🐕🦺 👷 ☑.
+
+👈, 👆 ⚙️ `app.add_middleware()` (🖼 ⚜).
+
+```Python
+from fastapi import FastAPI
+from unicorn import UnicornMiddleware
+
+app = FastAPI()
+
+app.add_middleware(UnicornMiddleware, some_config="rainbow")
+```
+
+`app.add_middleware()` 📨 🛠️ 🎓 🥇 ❌ & 🙆 🌖 ❌ 🚶♀️ 🛠️.
+
+## 🛠️ 🛠️
+
+**FastAPI** 🔌 📚 🛠️ ⚠ ⚙️ 💼, 👥 🔜 👀 ⏭ ❔ ⚙️ 👫.
+
+!!! note "📡 ℹ"
+ ⏭ 🖼, 👆 💪 ⚙️ `from starlette.middleware.something import SomethingMiddleware`.
+
+ **FastAPI** 🚚 📚 🛠️ `fastapi.middleware` 🏪 👆, 👩💻. ✋️ 🌅 💪 🛠️ 👟 🔗 ⚪️➡️ 💃.
+
+## `HTTPSRedirectMiddleware`
+
+🛠️ 👈 🌐 📨 📨 🔜 👯♂️ `https` ⚖️ `wss`.
+
+🙆 📨 📨 `http` ⚖️ `ws` 🔜 ❎ 🔐 ⚖ ↩️.
+
+```Python hl_lines="2 6"
+{!../../../docs_src/advanced_middleware/tutorial001.py!}
+```
+
+## `TrustedHostMiddleware`
+
+🛠️ 👈 🌐 📨 📨 ✔️ ☑ ⚒ `Host` 🎚, ✔ 💂♂ 🛡 🇺🇸🔍 🦠 🎚 👊.
+
+```Python hl_lines="2 6-8"
+{!../../../docs_src/advanced_middleware/tutorial002.py!}
+```
+
+📄 ❌ 🐕🦺:
+
+* `allowed_hosts` - 📇 🆔 📛 👈 🔜 ✔ 📛. 🃏 🆔 ✅ `*.example.com` 🐕🦺 🎀 📁. ✔ 🙆 📛 👯♂️ ⚙️ `allowed_hosts=["*"]` ⚖️ 🚫 🛠️.
+
+🚥 📨 📨 🔨 🚫 ✔ ☑ ⤴️ `400` 📨 🔜 📨.
+
+## `GZipMiddleware`
+
+🍵 🗜 📨 🙆 📨 👈 🔌 `"gzip"` `Accept-Encoding` 🎚.
+
+🛠️ 🔜 🍵 👯♂️ 🐩 & 🎥 📨.
+
+```Python hl_lines="2 6"
+{!../../../docs_src/advanced_middleware/tutorial003.py!}
+```
+
+📄 ❌ 🐕🦺:
+
+* `minimum_size` - 🚫 🗜 📨 👈 🤪 🌘 👉 💯 📐 🔢. 🔢 `500`.
+
+## 🎏 🛠️
+
+📤 📚 🎏 🔫 🛠️.
+
+🖼:
+
+* 🔫
+* Uvicorn `ProxyHeadersMiddleware`
+* 🇸🇲
+
+👀 🎏 💪 🛠️ ✅ 💃 🛠️ 🩺 & 🔫 👌 📇.
diff --git a/docs/em/docs/advanced/nosql-databases.md b/docs/em/docs/advanced/nosql-databases.md
new file mode 100644
index 000000000..9c828a909
--- /dev/null
+++ b/docs/em/docs/advanced/nosql-databases.md
@@ -0,0 +1,156 @@
+# ☁ (📎 / 🦏 💽) 💽
+
+**FastAPI** 💪 🛠️ ⏮️ 🙆 ☁.
+
+📥 👥 🔜 👀 🖼 ⚙️ **🗄**, 📄 🧢 ☁ 💽.
+
+👆 💪 🛠️ ⚫️ 🙆 🎏 ☁ 💽 💖:
+
+* **✳**
+* **👸**
+* **✳**
+* **🇸🇲**
+* **✳**, ♒️.
+
+!!! tip
+ 📤 🛂 🏗 🚂 ⏮️ **FastAPI** & **🗄**, 🌐 ⚓️ 🔛 **☁**, 🔌 🕸 & 🌖 🧰: https://github.com/tiangolo/full-stack-fastapi-couchbase
+
+## 🗄 🗄 🦲
+
+🔜, 🚫 💸 🙋 🎂, 🕴 🗄:
+
+```Python hl_lines="3-5"
+{!../../../docs_src/nosql_databases/tutorial001.py!}
+```
+
+## 🔬 📉 ⚙️ "📄 🆎"
+
+👥 🔜 ⚙️ ⚫️ ⏪ 🔧 🏑 `type` 👆 📄.
+
+👉 🚫 ✔ 🗄, ✋️ 👍 💡 👈 🔜 ℹ 👆 ⏮️.
+
+```Python hl_lines="9"
+{!../../../docs_src/nosql_databases/tutorial001.py!}
+```
+
+## 🚮 🔢 🤚 `Bucket`
+
+**🗄**, 🥡 ⚒ 📄, 👈 💪 🎏 🆎.
+
+👫 🛎 🌐 🔗 🎏 🈸.
+
+🔑 🔗 💽 🌏 🔜 "💽" (🎯 💽, 🚫 💽 💽).
+
+🔑 **✳** 🔜 "🗃".
+
+📟, `Bucket` 🎨 👑 🇨🇻 📻 ⏮️ 💽.
+
+👉 🚙 🔢 🔜:
+
+* 🔗 **🗄** 🌑 (👈 💪 👁 🎰).
+ * ⚒ 🔢 ⏲.
+* 🔓 🌑.
+* 🤚 `Bucket` 👐.
+ * ⚒ 🔢 ⏲.
+* 📨 ⚫️.
+
+```Python hl_lines="12-21"
+{!../../../docs_src/nosql_databases/tutorial001.py!}
+```
+
+## ✍ Pydantic 🏷
+
+**🗄** "📄" 🤙 "🎻 🎚", 👥 💪 🏷 👫 ⏮️ Pydantic.
+
+### `User` 🏷
+
+🥇, ➡️ ✍ `User` 🏷:
+
+```Python hl_lines="24-28"
+{!../../../docs_src/nosql_databases/tutorial001.py!}
+```
+
+👥 🔜 ⚙️ 👉 🏷 👆 *➡ 🛠️ 🔢*,, 👥 🚫 🔌 ⚫️ `hashed_password`.
+
+### `UserInDB` 🏷
+
+🔜, ➡️ ✍ `UserInDB` 🏷.
+
+👉 🔜 ✔️ 💽 👈 🤙 🏪 💽.
+
+👥 🚫 ✍ ⚫️ 🏿 Pydantic `BaseModel` ✋️ 🏿 👆 👍 `User`, ↩️ ⚫️ 🔜 ✔️ 🌐 🔢 `User` ➕ 👩❤👨 🌅:
+
+```Python hl_lines="31-33"
+{!../../../docs_src/nosql_databases/tutorial001.py!}
+```
+
+!!! note
+ 👀 👈 👥 ✔️ `hashed_password` & `type` 🏑 👈 🔜 🏪 💽.
+
+ ✋️ ⚫️ 🚫 🍕 🏢 `User` 🏷 (1️⃣ 👥 🔜 📨 *➡ 🛠️*).
+
+## 🤚 👩💻
+
+🔜 ✍ 🔢 👈 🔜:
+
+* ✊ 🆔.
+* 🏗 📄 🆔 ⚪️➡️ ⚫️.
+* 🤚 📄 ⏮️ 👈 🆔.
+* 🚮 🎚 📄 `UserInDB` 🏷.
+
+🏗 🔢 👈 🕴 💡 🤚 👆 👩💻 ⚪️➡️ `username` (⚖️ 🙆 🎏 🔢) 🔬 👆 *➡ 🛠️ 🔢*, 👆 💪 🌖 💪 🏤-⚙️ ⚫️ 💗 🍕 & 🚮 ⚒ 💯 ⚫️:
+
+```Python hl_lines="36-42"
+{!../../../docs_src/nosql_databases/tutorial001.py!}
+```
+
+### Ⓜ-🎻
+
+🚥 👆 🚫 😰 ⏮️ `f"userprofile::{username}"`, ⚫️ 🐍 "Ⓜ-🎻".
+
+🙆 🔢 👈 🚮 🔘 `{}` Ⓜ-🎻 🔜 ↔ / 💉 🎻.
+
+### `dict` 🏗
+
+🚥 👆 🚫 😰 ⏮️ `UserInDB(**result.value)`, ⚫️ ⚙️ `dict` "🏗".
+
+⚫️ 🔜 ✊ `dict` `result.value`, & ✊ 🔠 🚮 🔑 & 💲 & 🚶♀️ 👫 🔑-💲 `UserInDB` 🇨🇻 ❌.
+
+, 🚥 `dict` 🔌:
+
+```Python
+{
+ "username": "johndoe",
+ "hashed_password": "some_hash",
+}
+```
+
+⚫️ 🔜 🚶♀️ `UserInDB` :
+
+```Python
+UserInDB(username="johndoe", hashed_password="some_hash")
+```
+
+## ✍ 👆 **FastAPI** 📟
+
+### ✍ `FastAPI` 📱
+
+```Python hl_lines="46"
+{!../../../docs_src/nosql_databases/tutorial001.py!}
+```
+
+### ✍ *➡ 🛠️ 🔢*
+
+👆 📟 🤙 🗄 & 👥 🚫 ⚙️ 🥼 🐍 await 🐕🦺, 👥 🔜 📣 👆 🔢 ⏮️ 😐 `def` ↩️ `async def`.
+
+, 🗄 👍 🚫 ⚙️ 👁 `Bucket` 🎚 💗 "🧵Ⓜ",, 👥 💪 🤚 🥡 🔗 & 🚶♀️ ⚫️ 👆 🚙 🔢:
+
+```Python hl_lines="49-53"
+{!../../../docs_src/nosql_databases/tutorial001.py!}
+```
+
+## 🌃
+
+👆 💪 🛠️ 🙆 🥉 🥳 ☁ 💽, ⚙️ 👫 🐩 📦.
+
+🎏 ✔ 🙆 🎏 🔢 🧰, ⚙️ ⚖️ 🛠️.
diff --git a/docs/em/docs/advanced/openapi-callbacks.md b/docs/em/docs/advanced/openapi-callbacks.md
new file mode 100644
index 000000000..630b75ed2
--- /dev/null
+++ b/docs/em/docs/advanced/openapi-callbacks.md
@@ -0,0 +1,179 @@
+# 🗄 ⏲
+
+👆 💪 ✍ 🛠️ ⏮️ *➡ 🛠️* 👈 💪 ⏲ 📨 *🔢 🛠️* ✍ 👱 🙆 (🎲 🎏 👩💻 👈 🔜 *⚙️* 👆 🛠️).
+
+🛠️ 👈 🔨 🕐❔ 👆 🛠️ 📱 🤙 *🔢 🛠️* 📛 "⏲". ↩️ 🖥 👈 🔢 👩💻 ✍ 📨 📨 👆 🛠️ & ⤴️ 👆 🛠️ *🤙 🔙*, 📨 📨 *🔢 🛠️* (👈 🎲 ✍ 🎏 👩💻).
+
+👉 💼, 👆 💪 💚 📄 ❔ 👈 🔢 🛠️ *🔜* 👀 💖. ⚫️❔ *➡ 🛠️* ⚫️ 🔜 ✔️, ⚫️❔ 💪 ⚫️ 🔜 ⌛, ⚫️❔ 📨 ⚫️ 🔜 📨, ♒️.
+
+## 📱 ⏮️ ⏲
+
+➡️ 👀 🌐 👉 ⏮️ 🖼.
+
+🌈 👆 🛠️ 📱 👈 ✔ 🏗 🧾.
+
+👉 🧾 🔜 ✔️ `id`, `title` (📦), `customer`, & `total`.
+
+👩💻 👆 🛠️ (🔢 👩💻) 🔜 ✍ 🧾 👆 🛠️ ⏮️ 🏤 📨.
+
+⤴️ 👆 🛠️ 🔜 (➡️ 🌈):
+
+* 📨 🧾 🕴 🔢 👩💻.
+* 📈 💸.
+* 📨 📨 🔙 🛠️ 👩💻 (🔢 👩💻).
+ * 👉 🔜 🔨 📨 🏤 📨 (⚪️➡️ *👆 🛠️*) *🔢 🛠️* 🚚 👈 🔢 👩💻 (👉 "⏲").
+
+## 😐 **FastAPI** 📱
+
+➡️ 🥇 👀 ❔ 😐 🛠️ 📱 🔜 👀 💖 ⏭ ❎ ⏲.
+
+⚫️ 🔜 ✔️ *➡ 🛠️* 👈 🔜 📨 `Invoice` 💪, & 🔢 🔢 `callback_url` 👈 🔜 🔌 📛 ⏲.
+
+👉 🍕 📶 😐, 🌅 📟 🎲 ⏪ 😰 👆:
+
+```Python hl_lines="9-13 36-53"
+{!../../../docs_src/openapi_callbacks/tutorial001.py!}
+```
+
+!!! tip
+ `callback_url` 🔢 🔢 ⚙️ Pydantic 📛 🆎.
+
+🕴 🆕 👜 `callbacks=messages_callback_router.routes` ❌ *➡ 🛠️ 👨🎨*. 👥 🔜 👀 ⚫️❔ 👈 ⏭.
+
+## 🔬 ⏲
+
+☑ ⏲ 📟 🔜 🪀 🙇 🔛 👆 👍 🛠️ 📱.
+
+& ⚫️ 🔜 🎲 🪀 📚 ⚪️➡️ 1️⃣ 📱 ⏭.
+
+⚫️ 💪 1️⃣ ⚖️ 2️⃣ ⏸ 📟, 💖:
+
+```Python
+callback_url = "https://example.com/api/v1/invoices/events/"
+httpx.post(callback_url, json={"description": "Invoice paid", "paid": True})
+```
+
+✋️ 🎲 🏆 ⚠ 🍕 ⏲ ⚒ 💭 👈 👆 🛠️ 👩💻 (🔢 👩💻) 🛠️ *🔢 🛠️* ☑, 🛄 💽 👈 *👆 🛠️* 🔜 📨 📨 💪 ⏲, ♒️.
+
+, ⚫️❔ 👥 🔜 ⏭ 🚮 📟 📄 ❔ 👈 *🔢 🛠️* 🔜 👀 💖 📨 ⏲ ⚪️➡️ *👆 🛠️*.
+
+👈 🧾 🔜 🎦 🆙 🦁 🎚 `/docs` 👆 🛠️, & ⚫️ 🔜 ➡️ 🔢 👩💻 💭 ❔ 🏗 *🔢 🛠️*.
+
+👉 🖼 🚫 🛠️ ⏲ ⚫️ (👈 💪 ⏸ 📟), 🕴 🧾 🍕.
+
+!!! tip
+ ☑ ⏲ 🇺🇸🔍 📨.
+
+ 🕐❔ 🛠️ ⏲ 👆, 👆 💪 ⚙️ 🕳 💖 🇸🇲 ⚖️ 📨.
+
+## ✍ ⏲ 🧾 📟
+
+👉 📟 🏆 🚫 🛠️ 👆 📱, 👥 🕴 💪 ⚫️ *📄* ❔ 👈 *🔢 🛠️* 🔜 👀 💖.
+
+✋️, 👆 ⏪ 💭 ❔ 💪 ✍ 🏧 🧾 🛠️ ⏮️ **FastAPI**.
+
+👥 🔜 ⚙️ 👈 🎏 💡 📄 ❔ *🔢 🛠️* 🔜 👀 💖... 🏗 *➡ 🛠️(Ⓜ)* 👈 🔢 🛠️ 🔜 🛠️ (🕐 👆 🛠️ 🔜 🤙).
+
+!!! tip
+ 🕐❔ ✍ 📟 📄 ⏲, ⚫️ 💪 ⚠ 🌈 👈 👆 👈 *🔢 👩💻*. & 👈 👆 ⏳ 🛠️ *🔢 🛠️*, 🚫 *👆 🛠️*.
+
+ 🍕 🛠️ 👉 ☝ 🎑 ( *🔢 👩💻*) 💪 ℹ 👆 💭 💖 ⚫️ 🌅 ⭐ 🌐❔ 🚮 🔢, Pydantic 🏷 💪, 📨, ♒️. 👈 *🔢 🛠️*.
+
+### ✍ ⏲ `APIRouter`
+
+🥇 ✍ 🆕 `APIRouter` 👈 🔜 🔌 1️⃣ ⚖️ 🌅 ⏲.
+
+```Python hl_lines="3 25"
+{!../../../docs_src/openapi_callbacks/tutorial001.py!}
+```
+
+### ✍ ⏲ *➡ 🛠️*
+
+✍ ⏲ *➡ 🛠️* ⚙️ 🎏 `APIRouter` 👆 ✍ 🔛.
+
+⚫️ 🔜 👀 💖 😐 FastAPI *➡ 🛠️*:
+
+* ⚫️ 🔜 🎲 ✔️ 📄 💪 ⚫️ 🔜 📨, ✅ `body: InvoiceEvent`.
+* & ⚫️ 💪 ✔️ 📄 📨 ⚫️ 🔜 📨, ✅ `response_model=InvoiceEventReceived`.
+
+```Python hl_lines="16-18 21-22 28-32"
+{!../../../docs_src/openapi_callbacks/tutorial001.py!}
+```
+
+📤 2️⃣ 👑 🔺 ⚪️➡️ 😐 *➡ 🛠️*:
+
+* ⚫️ 🚫 💪 ✔️ 🙆 ☑ 📟, ↩️ 👆 📱 🔜 🙅 🤙 👉 📟. ⚫️ 🕴 ⚙️ 📄 *🔢 🛠️*. , 🔢 💪 ✔️ `pass`.
+* *➡* 💪 🔌 🗄 3️⃣ 🧬 (👀 🌖 🔛) 🌐❔ ⚫️ 💪 ⚙️ 🔢 ⏮️ 🔢 & 🍕 ⏮️ 📨 📨 *👆 🛠️*.
+
+### ⏲ ➡ 🧬
+
+⏲ *➡* 💪 ✔️ 🗄 3️⃣ 🧬 👈 💪 🔌 🍕 ⏮️ 📨 📨 *👆 🛠️*.
+
+👉 💼, ⚫️ `str`:
+
+```Python
+"{$callback_url}/invoices/{$request.body.id}"
+```
+
+, 🚥 👆 🛠️ 👩💻 (🔢 👩💻) 📨 📨 *👆 🛠️* :
+
+```
+https://yourapi.com/invoices/?callback_url=https://www.external.org/events
+```
+
+⏮️ 🎻 💪:
+
+```JSON
+{
+ "id": "2expen51ve",
+ "customer": "Mr. Richie Rich",
+ "total": "9999"
+}
+```
+
+⤴️ *👆 🛠️* 🔜 🛠️ 🧾, & ☝ ⏪, 📨 ⏲ 📨 `callback_url` ( *🔢 🛠️*):
+
+```
+https://www.external.org/events/invoices/2expen51ve
+```
+
+⏮️ 🎻 💪 ⚗ 🕳 💖:
+
+```JSON
+{
+ "description": "Payment celebration",
+ "paid": true
+}
+```
+
+& ⚫️ 🔜 ⌛ 📨 ⚪️➡️ 👈 *🔢 🛠️* ⏮️ 🎻 💪 💖:
+
+```JSON
+{
+ "ok": true
+}
+```
+
+!!! tip
+ 👀 ❔ ⏲ 📛 ⚙️ 🔌 📛 📨 🔢 🔢 `callback_url` (`https://www.external.org/events`) & 🧾 `id` ⚪️➡️ 🔘 🎻 💪 (`2expen51ve`).
+
+### 🚮 ⏲ 📻
+
+👉 ☝ 👆 ✔️ *⏲ ➡ 🛠️(Ⓜ)* 💪 (1️⃣(Ⓜ) 👈 *🔢 👩💻* 🔜 🛠️ *🔢 🛠️*) ⏲ 📻 👆 ✍ 🔛.
+
+🔜 ⚙️ 🔢 `callbacks` *👆 🛠️ ➡ 🛠️ 👨🎨* 🚶♀️ 🔢 `.routes` (👈 🤙 `list` 🛣/*➡ 🛠️*) ⚪️➡️ 👈 ⏲ 📻:
+
+```Python hl_lines="35"
+{!../../../docs_src/openapi_callbacks/tutorial001.py!}
+```
+
+!!! tip
+ 👀 👈 👆 🚫 🚶♀️ 📻 ⚫️ (`invoices_callback_router`) `callback=`, ✋️ 🔢 `.routes`, `invoices_callback_router.routes`.
+
+### ✅ 🩺
+
+🔜 👆 💪 ▶️ 👆 📱 ⏮️ Uvicorn & 🚶 http://127.0.0.1:8000/docs.
+
+👆 🔜 👀 👆 🩺 ✅ "⏲" 📄 👆 *➡ 🛠️* 👈 🎦 ❔ *🔢 🛠️* 🔜 👀 💖:
+
+
diff --git a/docs/em/docs/advanced/path-operation-advanced-configuration.md b/docs/em/docs/advanced/path-operation-advanced-configuration.md
new file mode 100644
index 000000000..ec7231870
--- /dev/null
+++ b/docs/em/docs/advanced/path-operation-advanced-configuration.md
@@ -0,0 +1,170 @@
+# ➡ 🛠️ 🏧 📳
+
+## 🗄 {
+
+!!! warning
+ 🚥 👆 🚫 "🕴" 🗄, 👆 🎲 🚫 💪 👉.
+
+👆 💪 ⚒ 🗄 `operationId` ⚙️ 👆 *➡ 🛠️* ⏮️ 🔢 `operation_id`.
+
+👆 🔜 ✔️ ⚒ 💭 👈 ⚫️ 😍 🔠 🛠️.
+
+```Python hl_lines="6"
+{!../../../docs_src/path_operation_advanced_configuration/tutorial001.py!}
+```
+
+### ⚙️ *➡ 🛠️ 🔢* 📛 {
+
+🚥 👆 💚 ⚙️ 👆 🔗' 🔢 📛 `operationId`Ⓜ, 👆 💪 🔁 🤭 🌐 👫 & 🔐 🔠 *➡ 🛠️* `operation_id` ⚙️ 👫 `APIRoute.name`.
+
+👆 🔜 ⚫️ ⏮️ ❎ 🌐 👆 *➡ 🛠️*.
+
+```Python hl_lines="2 12-21 24"
+{!../../../docs_src/path_operation_advanced_configuration/tutorial002.py!}
+```
+
+!!! tip
+ 🚥 👆 ❎ 🤙 `app.openapi()`, 👆 🔜 ℹ `operationId`Ⓜ ⏭ 👈.
+
+!!! warning
+ 🚥 👆 👉, 👆 ✔️ ⚒ 💭 🔠 1️⃣ 👆 *➡ 🛠️ 🔢* ✔️ 😍 📛.
+
+ 🚥 👫 🎏 🕹 (🐍 📁).
+
+## 🚫 ⚪️➡️ 🗄
+
+🚫 *➡ 🛠️* ⚪️➡️ 🏗 🗄 🔗 (& ➡️, ⚪️➡️ 🏧 🧾 ⚙️), ⚙️ 🔢 `include_in_schema` & ⚒ ⚫️ `False`:
+
+```Python hl_lines="6"
+{!../../../docs_src/path_operation_advanced_configuration/tutorial003.py!}
+```
+
+## 🏧 📛 ⚪️➡️ #️⃣
+
+👆 💪 📉 ⏸ ⚙️ ⚪️➡️ #️⃣ *➡ 🛠️ 🔢* 🗄.
+
+❎ `\f` (😖 "📨 🍼" 🦹) 🤕 **FastAPI** 🔁 🔢 ⚙️ 🗄 👉 ☝.
+
+⚫️ 🏆 🚫 🎦 🆙 🧾, ✋️ 🎏 🧰 (✅ 🐉) 🔜 💪 ⚙️ 🎂.
+
+```Python hl_lines="19-29"
+{!../../../docs_src/path_operation_advanced_configuration/tutorial004.py!}
+```
+
+## 🌖 📨
+
+👆 🎲 ✔️ 👀 ❔ 📣 `response_model` & `status_code` *➡ 🛠️*.
+
+👈 🔬 🗃 🔃 👑 📨 *➡ 🛠️*.
+
+👆 💪 📣 🌖 📨 ⏮️ 👫 🏷, 👔 📟, ♒️.
+
+📤 🎂 📃 📥 🧾 🔃 ⚫️, 👆 💪 ✍ ⚫️ [🌖 📨 🗄](./additional-responses.md){.internal-link target=_blank}.
+
+## 🗄 ➕
+
+🕐❔ 👆 📣 *➡ 🛠️* 👆 🈸, **FastAPI** 🔁 🏗 🔗 🗃 🔃 👈 *➡ 🛠️* 🔌 🗄 🔗.
+
+!!! note "📡 ℹ"
+ 🗄 🔧 ⚫️ 🤙 🛠️ 🎚.
+
+⚫️ ✔️ 🌐 ℹ 🔃 *➡ 🛠️* & ⚙️ 🏗 🏧 🧾.
+
+⚫️ 🔌 `tags`, `parameters`, `requestBody`, `responses`, ♒️.
+
+👉 *➡ 🛠️*-🎯 🗄 🔗 🛎 🏗 🔁 **FastAPI**, ✋️ 👆 💪 ↔ ⚫️.
+
+!!! tip
+ 👉 🔅 🎚 ↔ ☝.
+
+ 🚥 👆 🕴 💪 📣 🌖 📨, 🌅 🏪 🌌 ⚫️ ⏮️ [🌖 📨 🗄](./additional-responses.md){.internal-link target=_blank}.
+
+👆 💪 ↔ 🗄 🔗 *➡ 🛠️* ⚙️ 🔢 `openapi_extra`.
+
+### 🗄 ↔
+
+👉 `openapi_extra` 💪 👍, 🖼, 📣 [🗄 ↔](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions):
+
+```Python hl_lines="6"
+{!../../../docs_src/path_operation_advanced_configuration/tutorial005.py!}
+```
+
+🚥 👆 📂 🏧 🛠️ 🩺, 👆 ↔ 🔜 🎦 🆙 🔝 🎯 *➡ 🛠️*.
+
+
+
+& 🚥 👆 👀 📉 🗄 ( `/openapi.json` 👆 🛠️), 👆 🔜 👀 👆 ↔ 🍕 🎯 *➡ 🛠️* 💁♂️:
+
+```JSON hl_lines="22"
+{
+ "openapi": "3.0.2",
+ "info": {
+ "title": "FastAPI",
+ "version": "0.1.0"
+ },
+ "paths": {
+ "/items/": {
+ "get": {
+ "summary": "Read Items",
+ "operationId": "read_items_items__get",
+ "responses": {
+ "200": {
+ "description": "Successful Response",
+ "content": {
+ "application/json": {
+ "schema": {}
+ }
+ }
+ }
+ },
+ "x-aperture-labs-portal": "blue"
+ }
+ }
+ }
+}
+```
+
+### 🛃 🗄 *➡ 🛠️* 🔗
+
+📖 `openapi_extra` 🔜 🙇 🔗 ⏮️ 🔁 🏗 🗄 🔗 *➡ 🛠️*.
+
+, 👆 💪 🚮 🌖 💽 🔁 🏗 🔗.
+
+🖼, 👆 💪 💭 ✍ & ✔ 📨 ⏮️ 👆 👍 📟, 🍵 ⚙️ 🏧 ⚒ FastAPI ⏮️ Pydantic, ✋️ 👆 💪 💚 🔬 📨 🗄 🔗.
+
+👆 💪 👈 ⏮️ `openapi_extra`:
+
+```Python hl_lines="20-37 39-40"
+{!../../../docs_src/path_operation_advanced_configuration/tutorial006.py!}
+```
+
+👉 🖼, 👥 🚫 📣 🙆 Pydantic 🏷. 👐, 📨 💪 🚫 🎻 🎻, ⚫️ ✍ 🔗 `bytes`, & 🔢 `magic_data_reader()` 🔜 🈚 🎻 ⚫️ 🌌.
+
+👐, 👥 💪 📣 📈 🔗 📨 💪.
+
+### 🛃 🗄 🎚 🆎
+
+⚙️ 👉 🎏 🎱, 👆 💪 ⚙️ Pydantic 🏷 🔬 🎻 🔗 👈 ⤴️ 🔌 🛃 🗄 🔗 📄 *➡ 🛠️*.
+
+& 👆 💪 👉 🚥 💽 🆎 📨 🚫 🎻.
+
+🖼, 👉 🈸 👥 🚫 ⚙️ FastAPI 🛠️ 🛠️ ⚗ 🎻 🔗 ⚪️➡️ Pydantic 🏷 🚫 🏧 🔬 🎻. 👐, 👥 📣 📨 🎚 🆎 📁, 🚫 🎻:
+
+```Python hl_lines="17-22 24"
+{!../../../docs_src/path_operation_advanced_configuration/tutorial007.py!}
+```
+
+👐, 👐 👥 🚫 ⚙️ 🔢 🛠️ 🛠️, 👥 ⚙️ Pydantic 🏷 ❎ 🏗 🎻 🔗 💽 👈 👥 💚 📨 📁.
+
+⤴️ 👥 ⚙️ 📨 🔗, & ⚗ 💪 `bytes`. 👉 ⛓ 👈 FastAPI 🏆 🚫 🔄 🎻 📨 🚀 🎻.
+
+& ⤴️ 👆 📟, 👥 🎻 👈 📁 🎚 🔗, & ⤴️ 👥 🔄 ⚙️ 🎏 Pydantic 🏷 ✔ 📁 🎚:
+
+```Python hl_lines="26-33"
+{!../../../docs_src/path_operation_advanced_configuration/tutorial007.py!}
+```
+
+!!! tip
+ 📥 👥 🏤-⚙️ 🎏 Pydantic 🏷.
+
+ ✋️ 🎏 🌌, 👥 💪 ✔️ ✔ ⚫️ 🎏 🌌.
diff --git a/docs/em/docs/advanced/response-change-status-code.md b/docs/em/docs/advanced/response-change-status-code.md
new file mode 100644
index 000000000..156efcc16
--- /dev/null
+++ b/docs/em/docs/advanced/response-change-status-code.md
@@ -0,0 +1,33 @@
+# 📨 - 🔀 👔 📟
+
+👆 🎲 ✍ ⏭ 👈 👆 💪 ⚒ 🔢 [📨 👔 📟](../tutorial/response-status-code.md){.internal-link target=_blank}.
+
+✋️ 💼 👆 💪 📨 🎏 👔 📟 🌘 🔢.
+
+## ⚙️ 💼
+
+🖼, 🌈 👈 👆 💚 📨 🇺🇸🔍 👔 📟 "👌" `200` 🔢.
+
+✋️ 🚥 💽 🚫 🔀, 👆 💚 ✍ ⚫️, & 📨 🇺🇸🔍 👔 📟 "✍" `201`.
+
+✋️ 👆 💚 💪 ⛽ & 🗜 💽 👆 📨 ⏮️ `response_model`.
+
+📚 💼, 👆 💪 ⚙️ `Response` 🔢.
+
+## ⚙️ `Response` 🔢
+
+👆 💪 📣 🔢 🆎 `Response` 👆 *➡ 🛠️ 🔢* (👆 💪 🍪 & 🎚).
+
+& ⤴️ 👆 💪 ⚒ `status_code` 👈 *🔀* 📨 🎚.
+
+```Python hl_lines="1 9 12"
+{!../../../docs_src/response_change_status_code/tutorial001.py!}
+```
+
+& ⤴️ 👆 💪 📨 🙆 🎚 👆 💪, 👆 🛎 🔜 ( `dict`, 💽 🏷, ♒️).
+
+& 🚥 👆 📣 `response_model`, ⚫️ 🔜 ⚙️ ⛽ & 🗜 🎚 👆 📨.
+
+**FastAPI** 🔜 ⚙️ 👈 *🔀* 📨 ⚗ 👔 📟 (🍪 & 🎚), & 🔜 🚮 👫 🏁 📨 👈 🔌 💲 👆 📨, ⛽ 🙆 `response_model`.
+
+👆 💪 📣 `Response` 🔢 🔗, & ⚒ 👔 📟 👫. ✋️ ✔️ 🤯 👈 🏁 1️⃣ ⚒ 🔜 🏆.
diff --git a/docs/em/docs/advanced/response-cookies.md b/docs/em/docs/advanced/response-cookies.md
new file mode 100644
index 000000000..23fffe1dd
--- /dev/null
+++ b/docs/em/docs/advanced/response-cookies.md
@@ -0,0 +1,49 @@
+# 📨 🍪
+
+## ⚙️ `Response` 🔢
+
+👆 💪 📣 🔢 🆎 `Response` 👆 *➡ 🛠️ 🔢*.
+
+& ⤴️ 👆 💪 ⚒ 🍪 👈 *🔀* 📨 🎚.
+
+```Python hl_lines="1 8-9"
+{!../../../docs_src/response_cookies/tutorial002.py!}
+```
+
+& ⤴️ 👆 💪 📨 🙆 🎚 👆 💪, 👆 🛎 🔜 ( `dict`, 💽 🏷, ♒️).
+
+& 🚥 👆 📣 `response_model`, ⚫️ 🔜 ⚙️ ⛽ & 🗜 🎚 👆 📨.
+
+**FastAPI** 🔜 ⚙️ 👈 *🔀* 📨 ⚗ 🍪 (🎚 & 👔 📟), & 🔜 🚮 👫 🏁 📨 👈 🔌 💲 👆 📨, ⛽ 🙆 `response_model`.
+
+👆 💪 📣 `Response` 🔢 🔗, & ⚒ 🍪 (& 🎚) 👫.
+
+## 📨 `Response` 🔗
+
+👆 💪 ✍ 🍪 🕐❔ 🛬 `Response` 🔗 👆 📟.
+
+👈, 👆 💪 ✍ 📨 🔬 [📨 📨 🔗](response-directly.md){.internal-link target=_blank}.
+
+⤴️ ⚒ 🍪 ⚫️, & ⤴️ 📨 ⚫️:
+
+```Python hl_lines="10-12"
+{!../../../docs_src/response_cookies/tutorial001.py!}
+```
+
+!!! tip
+ ✔️ 🤯 👈 🚥 👆 📨 📨 🔗 ↩️ ⚙️ `Response` 🔢, FastAPI 🔜 📨 ⚫️ 🔗.
+
+ , 👆 🔜 ✔️ ⚒ 💭 👆 💽 ☑ 🆎. 🤶 Ⓜ. ⚫️ 🔗 ⏮️ 🎻, 🚥 👆 🛬 `JSONResponse`.
+
+ & 👈 👆 🚫 📨 🙆 📊 👈 🔜 ✔️ ⛽ `response_model`.
+
+### 🌅 ℹ
+
+!!! note "📡 ℹ"
+ 👆 💪 ⚙️ `from starlette.responses import Response` ⚖️ `from starlette.responses import JSONResponse`.
+
+ **FastAPI** 🚚 🎏 `starlette.responses` `fastapi.responses` 🏪 👆, 👩💻. ✋️ 🌅 💪 📨 👟 🔗 ⚪️➡️ 💃.
+
+ & `Response` 💪 ⚙️ 🛎 ⚒ 🎚 & 🍪, **FastAPI** 🚚 ⚫️ `fastapi.Response`.
+
+👀 🌐 💪 🔢 & 🎛, ✅ 🧾 💃.
diff --git a/docs/em/docs/advanced/response-directly.md b/docs/em/docs/advanced/response-directly.md
new file mode 100644
index 000000000..ba09734fb
--- /dev/null
+++ b/docs/em/docs/advanced/response-directly.md
@@ -0,0 +1,63 @@
+# 📨 📨 🔗
+
+🕐❔ 👆 ✍ **FastAPI** *➡ 🛠️* 👆 💪 🛎 📨 🙆 📊 ⚪️➡️ ⚫️: `dict`, `list`, Pydantic 🏷, 💽 🏷, ♒️.
+
+🔢, **FastAPI** 🔜 🔁 🗜 👈 📨 💲 🎻 ⚙️ `jsonable_encoder` 🔬 [🎻 🔗 🔢](../tutorial/encoder.md){.internal-link target=_blank}.
+
+⤴️, ⛅ 🎑, ⚫️ 🔜 🚮 👈 🎻-🔗 💽 (✅ `dict`) 🔘 `JSONResponse` 👈 🔜 ⚙️ 📨 📨 👩💻.
+
+✋️ 👆 💪 📨 `JSONResponse` 🔗 ⚪️➡️ 👆 *➡ 🛠️*.
+
+⚫️ 💪 ⚠, 🖼, 📨 🛃 🎚 ⚖️ 🍪.
+
+## 📨 `Response`
+
+👐, 👆 💪 📨 🙆 `Response` ⚖️ 🙆 🎧-🎓 ⚫️.
+
+!!! tip
+ `JSONResponse` ⚫️ 🎧-🎓 `Response`.
+
+& 🕐❔ 👆 📨 `Response`, **FastAPI** 🔜 🚶♀️ ⚫️ 🔗.
+
+⚫️ 🏆 🚫 🙆 💽 🛠️ ⏮️ Pydantic 🏷, ⚫️ 🏆 🚫 🗜 🎚 🙆 🆎, ♒️.
+
+👉 🤝 👆 📚 💪. 👆 💪 📨 🙆 📊 🆎, 🔐 🙆 💽 📄 ⚖️ 🔬, ♒️.
+
+## ⚙️ `jsonable_encoder` `Response`
+
+↩️ **FastAPI** 🚫 🙆 🔀 `Response` 👆 📨, 👆 ✔️ ⚒ 💭 ⚫️ 🎚 🔜 ⚫️.
+
+🖼, 👆 🚫🔜 🚮 Pydantic 🏷 `JSONResponse` 🍵 🥇 🏭 ⚫️ `dict` ⏮️ 🌐 📊 🆎 (💖 `datetime`, `UUID`, ♒️) 🗜 🎻-🔗 🆎.
+
+📚 💼, 👆 💪 ⚙️ `jsonable_encoder` 🗜 👆 📊 ⏭ 🚶♀️ ⚫️ 📨:
+
+```Python hl_lines="6-7 21-22"
+{!../../../docs_src/response_directly/tutorial001.py!}
+```
+
+!!! note "📡 ℹ"
+ 👆 💪 ⚙️ `from starlette.responses import JSONResponse`.
+
+ **FastAPI** 🚚 🎏 `starlette.responses` `fastapi.responses` 🏪 👆, 👩💻. ✋️ 🌅 💪 📨 👟 🔗 ⚪️➡️ 💃.
+
+## 🛬 🛃 `Response`
+
+🖼 🔛 🎦 🌐 🍕 👆 💪, ✋️ ⚫️ 🚫 📶 ⚠, 👆 💪 ✔️ 📨 `item` 🔗, & **FastAPI** 🔜 🚮 ⚫️ `JSONResponse` 👆, 🏭 ⚫️ `dict`, ♒️. 🌐 👈 🔢.
+
+🔜, ➡️ 👀 ❔ 👆 💪 ⚙️ 👈 📨 🛃 📨.
+
+➡️ 💬 👈 👆 💚 📨 📂 📨.
+
+👆 💪 🚮 👆 📂 🎚 🎻, 🚮 ⚫️ `Response`, & 📨 ⚫️:
+
+```Python hl_lines="1 18"
+{!../../../docs_src/response_directly/tutorial002.py!}
+```
+
+## 🗒
+
+🕐❔ 👆 📨 `Response` 🔗 🚮 📊 🚫 ✔, 🗜 (🎻), 🚫 📄 🔁.
+
+✋️ 👆 💪 📄 ⚫️ 🔬 [🌖 📨 🗄](additional-responses.md){.internal-link target=_blank}.
+
+👆 💪 👀 ⏪ 📄 ❔ ⚙️/📣 👉 🛃 `Response`Ⓜ ⏪ ✔️ 🏧 💽 🛠️, 🧾, ♒️.
diff --git a/docs/em/docs/advanced/response-headers.md b/docs/em/docs/advanced/response-headers.md
new file mode 100644
index 000000000..de798982a
--- /dev/null
+++ b/docs/em/docs/advanced/response-headers.md
@@ -0,0 +1,42 @@
+# 📨 🎚
+
+## ⚙️ `Response` 🔢
+
+👆 💪 📣 🔢 🆎 `Response` 👆 *➡ 🛠️ 🔢* (👆 💪 🍪).
+
+& ⤴️ 👆 💪 ⚒ 🎚 👈 *🔀* 📨 🎚.
+
+```Python hl_lines="1 7-8"
+{!../../../docs_src/response_headers/tutorial002.py!}
+```
+
+& ⤴️ 👆 💪 📨 🙆 🎚 👆 💪, 👆 🛎 🔜 ( `dict`, 💽 🏷, ♒️).
+
+& 🚥 👆 📣 `response_model`, ⚫️ 🔜 ⚙️ ⛽ & 🗜 🎚 👆 📨.
+
+**FastAPI** 🔜 ⚙️ 👈 *🔀* 📨 ⚗ 🎚 (🍪 & 👔 📟), & 🔜 🚮 👫 🏁 📨 👈 🔌 💲 👆 📨, ⛽ 🙆 `response_model`.
+
+👆 💪 📣 `Response` 🔢 🔗, & ⚒ 🎚 (& 🍪) 👫.
+
+## 📨 `Response` 🔗
+
+👆 💪 🚮 🎚 🕐❔ 👆 📨 `Response` 🔗.
+
+✍ 📨 🔬 [📨 📨 🔗](response-directly.md){.internal-link target=_blank} & 🚶♀️ 🎚 🌖 🔢:
+
+```Python hl_lines="10-12"
+{!../../../docs_src/response_headers/tutorial001.py!}
+```
+
+!!! note "📡 ℹ"
+ 👆 💪 ⚙️ `from starlette.responses import Response` ⚖️ `from starlette.responses import JSONResponse`.
+
+ **FastAPI** 🚚 🎏 `starlette.responses` `fastapi.responses` 🏪 👆, 👩💻. ✋️ 🌅 💪 📨 👟 🔗 ⚪️➡️ 💃.
+
+ & `Response` 💪 ⚙️ 🛎 ⚒ 🎚 & 🍪, **FastAPI** 🚚 ⚫️ `fastapi.Response`.
+
+## 🛃 🎚
+
+✔️ 🤯 👈 🛃 © 🎚 💪 🚮 ⚙️ '✖-' 🔡.
+
+✋️ 🚥 👆 ✔️ 🛃 🎚 👈 👆 💚 👩💻 🖥 💪 👀, 👆 💪 🚮 👫 👆 ⚜ 📳 (✍ 🌅 [⚜ (✖️-🇨🇳 ℹ 🤝)](../tutorial/cors.md){.internal-link target=_blank}), ⚙️ 🔢 `expose_headers` 📄 💃 ⚜ 🩺.
diff --git a/docs/em/docs/advanced/security/http-basic-auth.md b/docs/em/docs/advanced/security/http-basic-auth.md
new file mode 100644
index 000000000..33470a726
--- /dev/null
+++ b/docs/em/docs/advanced/security/http-basic-auth.md
@@ -0,0 +1,113 @@
+# 🇺🇸🔍 🔰 🔐
+
+🙅 💼, 👆 💪 ⚙️ 🇺🇸🔍 🔰 🔐.
+
+🇺🇸🔍 🔰 🔐, 🈸 ⌛ 🎚 👈 🔌 🆔 & 🔐.
+
+🚥 ⚫️ 🚫 📨 ⚫️, ⚫️ 📨 🇺🇸🔍 4️⃣0️⃣1️⃣ "⛔" ❌.
+
+& 📨 🎚 `WWW-Authenticate` ⏮️ 💲 `Basic`, & 📦 `realm` 🔢.
+
+👈 💬 🖥 🎦 🛠️ 📋 🆔 & 🔐.
+
+⤴️, 🕐❔ 👆 🆎 👈 🆔 & 🔐, 🖥 📨 👫 🎚 🔁.
+
+## 🙅 🇺🇸🔍 🔰 🔐
+
+* 🗄 `HTTPBasic` & `HTTPBasicCredentials`.
+* ✍ "`security` ⚖" ⚙️ `HTTPBasic`.
+* ⚙️ 👈 `security` ⏮️ 🔗 👆 *➡ 🛠️*.
+* ⚫️ 📨 🎚 🆎 `HTTPBasicCredentials`:
+ * ⚫️ 🔌 `username` & `password` 📨.
+
+```Python hl_lines="2 6 10"
+{!../../../docs_src/security/tutorial006.py!}
+```
+
+🕐❔ 👆 🔄 📂 📛 🥇 🕰 (⚖️ 🖊 "🛠️" 🔼 🩺) 🖥 🔜 💭 👆 👆 🆔 & 🔐:
+
+
+
+## ✅ 🆔
+
+📥 🌅 🏁 🖼.
+
+⚙️ 🔗 ✅ 🚥 🆔 & 🔐 ☑.
+
+👉, ⚙️ 🐍 🐩 🕹 `secrets` ✅ 🆔 & 🔐.
+
+`secrets.compare_digest()` 💪 ✊ `bytes` ⚖️ `str` 👈 🕴 🔌 🔠 🦹 (🕐 🇪🇸), 👉 ⛓ ⚫️ 🚫🔜 👷 ⏮️ 🦹 💖 `á`, `Sebastián`.
+
+🍵 👈, 👥 🥇 🗜 `username` & `password` `bytes` 🔢 👫 ⏮️ 🔠-8️⃣.
+
+⤴️ 👥 💪 ⚙️ `secrets.compare_digest()` 🚚 👈 `credentials.username` `"stanleyjobson"`, & 👈 `credentials.password` `"swordfish"`.
+
+```Python hl_lines="1 11-21"
+{!../../../docs_src/security/tutorial007.py!}
+```
+
+👉 🔜 🎏:
+
+```Python
+if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"):
+ # Return some error
+ ...
+```
+
+✋️ ⚙️ `secrets.compare_digest()` ⚫️ 🔜 🔐 🛡 🆎 👊 🤙 "🕰 👊".
+
+### ⏲ 👊
+
+✋️ ⚫️❔ "⏲ 👊"❓
+
+➡️ 🌈 👊 🔄 💭 🆔 & 🔐.
+
+& 👫 📨 📨 ⏮️ 🆔 `johndoe` & 🔐 `love123`.
+
+⤴️ 🐍 📟 👆 🈸 🔜 🌓 🕳 💖:
+
+```Python
+if "johndoe" == "stanleyjobson" and "love123" == "swordfish":
+ ...
+```
+
+✋️ ▶️️ 🙍 🐍 🔬 🥇 `j` `johndoe` 🥇 `s` `stanleyjobson`, ⚫️ 🔜 📨 `False`, ↩️ ⚫️ ⏪ 💭 👈 📚 2️⃣ 🎻 🚫 🎏, 💭 👈 "📤 🙅♂ 💪 🗑 🌅 📊 ⚖ 🎂 🔤". & 👆 🈸 🔜 💬 "❌ 👩💻 ⚖️ 🔐".
+
+✋️ ⤴️ 👊 🔄 ⏮️ 🆔 `stanleyjobsox` & 🔐 `love123`.
+
+& 👆 🈸 📟 🔨 🕳 💖:
+
+```Python
+if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish":
+ ...
+```
+
+🐍 🔜 ✔️ 🔬 🎂 `stanleyjobso` 👯♂️ `stanleyjobsox` & `stanleyjobson` ⏭ 🤔 👈 👯♂️ 🎻 🚫 🎏. ⚫️ 🔜 ✊ ➕ ⏲ 📨 🔙 "❌ 👩💻 ⚖️ 🔐".
+
+#### 🕰 ❔ ℹ 👊
+
+👈 ☝, 👀 👈 💽 ✊ ⏲ 📏 📨 "❌ 👩💻 ⚖️ 🔐" 📨, 👊 🔜 💭 👈 👫 🤚 _🕳_ ▶️️, ▶️ 🔤 ▶️️.
+
+& ⤴️ 👫 💪 🔄 🔄 🤔 👈 ⚫️ 🎲 🕳 🌖 🎏 `stanleyjobsox` 🌘 `johndoe`.
+
+#### "🕴" 👊
+
+↗️, 👊 🔜 🚫 🔄 🌐 👉 ✋, 👫 🔜 ✍ 📋 ⚫️, 🎲 ⏮️ 💯 ⚖️ 💯 💯 📍 🥈. & 🔜 🤚 1️⃣ ➕ ☑ 🔤 🕰.
+
+✋️ 🔨 👈, ⏲ ⚖️ 📆 👊 🔜 ✔️ 💭 ☑ 🆔 & 🔐, ⏮️ "ℹ" 👆 🈸, ⚙️ 🕰 ✊ ❔.
+
+#### 🔧 ⚫️ ⏮️ `secrets.compare_digest()`
+
+✋️ 👆 📟 👥 🤙 ⚙️ `secrets.compare_digest()`.
+
+📏, ⚫️ 🔜 ✊ 🎏 🕰 🔬 `stanleyjobsox` `stanleyjobson` 🌘 ⚫️ ✊ 🔬 `johndoe` `stanleyjobson`. & 🎏 🔐.
+
+👈 🌌, ⚙️ `secrets.compare_digest()` 👆 🈸 📟, ⚫️ 🔜 🔒 🛡 👉 🎂 ↔ 💂♂ 👊.
+
+### 📨 ❌
+
+⏮️ 🔍 👈 🎓 ❌, 📨 `HTTPException` ⏮️ 👔 📟 4️⃣0️⃣1️⃣ (🎏 📨 🕐❔ 🙅♂ 🎓 🚚) & 🚮 🎚 `WWW-Authenticate` ⚒ 🖥 🎦 💳 📋 🔄:
+
+```Python hl_lines="23-27"
+{!../../../docs_src/security/tutorial007.py!}
+```
diff --git a/docs/em/docs/advanced/security/index.md b/docs/em/docs/advanced/security/index.md
new file mode 100644
index 000000000..20ee85553
--- /dev/null
+++ b/docs/em/docs/advanced/security/index.md
@@ -0,0 +1,16 @@
+# 🏧 💂♂ - 🎶
+
+## 🌖 ⚒
+
+📤 ➕ ⚒ 🍵 💂♂ ↖️ ⚪️➡️ 🕐 📔 [🔰 - 👩💻 🦮: 💂♂](../../tutorial/security/){.internal-link target=_blank}.
+
+!!! tip
+ ⏭ 📄 **🚫 🎯 "🏧"**.
+
+ & ⚫️ 💪 👈 👆 ⚙️ 💼, ⚗ 1️⃣ 👫.
+
+## ✍ 🔰 🥇
+
+⏭ 📄 🤔 👆 ⏪ ✍ 👑 [🔰 - 👩💻 🦮: 💂♂](../../tutorial/security/){.internal-link target=_blank}.
+
+👫 🌐 ⚓️ 🔛 🎏 🔧, ✋️ ✔ ➕ 🛠️.
diff --git a/docs/em/docs/advanced/security/oauth2-scopes.md b/docs/em/docs/advanced/security/oauth2-scopes.md
new file mode 100644
index 000000000..a4684352c
--- /dev/null
+++ b/docs/em/docs/advanced/security/oauth2-scopes.md
@@ -0,0 +1,269 @@
+# Oauth2️⃣ ↔
+
+👆 💪 ⚙️ Oauth2️⃣ ↔ 🔗 ⏮️ **FastAPI**, 👫 🛠️ 👷 💎.
+
+👉 🔜 ✔ 👆 ✔️ 🌖 👌-🧽 ✔ ⚙️, 📄 Oauth2️⃣ 🐩, 🛠️ 🔘 👆 🗄 🈸 (& 🛠️ 🩺).
+
+Oauth2️⃣ ⏮️ ↔ 🛠️ ⚙️ 📚 🦏 🤝 🐕🦺, 💖 👱📔, 🇺🇸🔍, 📂, 🤸♂, 👱📔, ♒️. 👫 ⚙️ ⚫️ 🚚 🎯 ✔ 👩💻 & 🈸.
+
+🔠 🕰 👆 "🕹 ⏮️" 👱📔, 🇺🇸🔍, 📂, 🤸♂, 👱📔, 👈 🈸 ⚙️ Oauth2️⃣ ⏮️ ↔.
+
+👉 📄 👆 🔜 👀 ❔ 🛠️ 🤝 & ✔ ⏮️ 🎏 Oauth2️⃣ ⏮️ ↔ 👆 **FastAPI** 🈸.
+
+!!! warning
+ 👉 🌅 ⚖️ 🌘 🏧 📄. 🚥 👆 ▶️, 👆 💪 🚶 ⚫️.
+
+ 👆 🚫 🎯 💪 Oauth2️⃣ ↔, & 👆 💪 🍵 🤝 & ✔ 👐 👆 💚.
+
+ ✋️ Oauth2️⃣ ⏮️ ↔ 💪 🎆 🛠️ 🔘 👆 🛠️ (⏮️ 🗄) & 👆 🛠️ 🩺.
+
+ 👐, 👆 🛠️ 📚 ↔, ⚖️ 🙆 🎏 💂♂/✔ 📄, 👐 👆 💪, 👆 📟.
+
+ 📚 💼, Oauth2️⃣ ⏮️ ↔ 💪 👹.
+
+ ✋️ 🚥 👆 💭 👆 💪 ⚫️, ⚖️ 👆 😟, 🚧 👂.
+
+## Oauth2️⃣ ↔ & 🗄
+
+Oauth2️⃣ 🔧 🔬 "↔" 📇 🎻 🎏 🚀.
+
+🎚 🔠 👉 🎻 💪 ✔️ 🙆 📁, ✋️ 🔜 🚫 🔌 🚀.
+
+👫 ↔ 🎨 "✔".
+
+🗄 (✅ 🛠️ 🩺), 👆 💪 🔬 "💂♂ ⚖".
+
+🕐❔ 1️⃣ 👫 💂♂ ⚖ ⚙️ Oauth2️⃣, 👆 💪 📣 & ⚙️ ↔.
+
+🔠 "↔" 🎻 (🍵 🚀).
+
+👫 🛎 ⚙️ 📣 🎯 💂♂ ✔, 🖼:
+
+* `users:read` ⚖️ `users:write` ⚠ 🖼.
+* `instagram_basic` ⚙️ 👱📔 / 👱📔.
+* `https://www.googleapis.com/auth/drive` ⚙️ 🇺🇸🔍.
+
+!!! info
+ Oauth2️⃣ "↔" 🎻 👈 📣 🎯 ✔ ✔.
+
+ ⚫️ 🚫 🤔 🚥 ⚫️ ✔️ 🎏 🦹 💖 `:` ⚖️ 🚥 ⚫️ 📛.
+
+ 👈 ℹ 🛠️ 🎯.
+
+ Oauth2️⃣ 👫 🎻.
+
+## 🌐 🎑
+
+🥇, ➡️ 🔜 👀 🍕 👈 🔀 ⚪️➡️ 🖼 👑 **🔰 - 👩💻 🦮** [Oauth2️⃣ ⏮️ 🔐 (& 🔁), 📨 ⏮️ 🥙 🤝](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. 🔜 ⚙️ Oauth2️⃣ ↔:
+
+```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 153"
+{!../../../docs_src/security/tutorial005.py!}
+```
+
+🔜 ➡️ 📄 👈 🔀 🔁 🔁.
+
+## Oauth2️⃣ 💂♂ ⚖
+
+🥇 🔀 👈 🔜 👥 📣 Oauth2️⃣ 💂♂ ⚖ ⏮️ 2️⃣ 💪 ↔, `me` & `items`.
+
+`scopes` 🔢 📨 `dict` ⏮️ 🔠 ↔ 🔑 & 📛 💲:
+
+```Python hl_lines="62-65"
+{!../../../docs_src/security/tutorial005.py!}
+```
+
+↩️ 👥 🔜 📣 📚 ↔, 👫 🔜 🎦 🆙 🛠️ 🩺 🕐❔ 👆 🕹-/✔.
+
+& 👆 🔜 💪 🖊 ❔ ↔ 👆 💚 🤝 🔐: `me` & `items`.
+
+👉 🎏 🛠️ ⚙️ 🕐❔ 👆 🤝 ✔ ⏪ 🚨 ⏮️ 👱📔, 🇺🇸🔍, 📂, ♒️:
+
+
+
+## 🥙 🤝 ⏮️ ↔
+
+🔜, 🔀 🤝 *➡ 🛠️* 📨 ↔ 📨.
+
+👥 ⚙️ 🎏 `OAuth2PasswordRequestForm`. ⚫️ 🔌 🏠 `scopes` ⏮️ `list` `str`, ⏮️ 🔠 ↔ ⚫️ 📨 📨.
+
+& 👥 📨 ↔ 🍕 🥙 🤝.
+
+!!! danger
+ 🦁, 📥 👥 ❎ ↔ 📨 🔗 🤝.
+
+ ✋️ 👆 🈸, 💂♂, 👆 🔜 ⚒ 💭 👆 🕴 🚮 ↔ 👈 👩💻 🤙 💪 ✔️, ⚖️ 🕐 👆 ✔️ 🔁.
+
+```Python hl_lines="153"
+{!../../../docs_src/security/tutorial005.py!}
+```
+
+## 📣 ↔ *➡ 🛠️* & 🔗
+
+🔜 👥 📣 👈 *➡ 🛠️* `/users/me/items/` 🚚 ↔ `items`.
+
+👉, 👥 🗄 & ⚙️ `Security` ⚪️➡️ `fastapi`.
+
+👆 💪 ⚙️ `Security` 📣 🔗 (💖 `Depends`), ✋️ `Security` 📨 🔢 `scopes` ⏮️ 📇 ↔ (🎻).
+
+👉 💼, 👥 🚶♀️ 🔗 🔢 `get_current_active_user` `Security` (🎏 🌌 👥 🔜 ⏮️ `Depends`).
+
+✋️ 👥 🚶♀️ `list` ↔, 👉 💼 ⏮️ 1️⃣ ↔: `items` (⚫️ 💪 ✔️ 🌅).
+
+& 🔗 🔢 `get_current_active_user` 💪 📣 🎧-🔗, 🚫 🕴 ⏮️ `Depends` ✋️ ⏮️ `Security`. 📣 🚮 👍 🎧-🔗 🔢 (`get_current_user`), & 🌖 ↔ 📄.
+
+👉 💼, ⚫️ 🚚 ↔ `me` (⚫️ 💪 🚚 🌅 🌘 1️⃣ ↔).
+
+!!! note
+ 👆 🚫 🎯 💪 🚮 🎏 ↔ 🎏 🥉.
+
+ 👥 🔨 ⚫️ 📥 🎦 ❔ **FastAPI** 🍵 ↔ 📣 🎏 🎚.
+
+```Python hl_lines="4 139 166"
+{!../../../docs_src/security/tutorial005.py!}
+```
+
+!!! info "📡 ℹ"
+ `Security` 🤙 🏿 `Depends`, & ⚫️ ✔️ 1️⃣ ➕ 🔢 👈 👥 🔜 👀 ⏪.
+
+ ✋️ ⚙️ `Security` ↩️ `Depends`, **FastAPI** 🔜 💭 👈 ⚫️ 💪 📣 💂♂ ↔, ⚙️ 👫 🔘, & 📄 🛠️ ⏮️ 🗄.
+
+ ✋️ 🕐❔ 👆 🗄 `Query`, `Path`, `Depends`, `Security` & 🎏 ⚪️➡️ `fastapi`, 👈 🤙 🔢 👈 📨 🎁 🎓.
+
+## ⚙️ `SecurityScopes`
+
+🔜 ℹ 🔗 `get_current_user`.
+
+👉 1️⃣ ⚙️ 🔗 🔛.
+
+📥 👥 ⚙️ 🎏 Oauth2️⃣ ⚖ 👥 ✍ ⏭, 📣 ⚫️ 🔗: `oauth2_scheme`.
+
+↩️ 👉 🔗 🔢 🚫 ✔️ 🙆 ↔ 📄 ⚫️, 👥 💪 ⚙️ `Depends` ⏮️ `oauth2_scheme`, 👥 🚫 ✔️ ⚙️ `Security` 🕐❔ 👥 🚫 💪 ✔ 💂♂ ↔.
+
+👥 📣 🎁 🔢 🆎 `SecurityScopes`, 🗄 ⚪️➡️ `fastapi.security`.
+
+👉 `SecurityScopes` 🎓 🎏 `Request` (`Request` ⚙️ 🤚 📨 🎚 🔗).
+
+```Python hl_lines="8 105"
+{!../../../docs_src/security/tutorial005.py!}
+```
+
+## ⚙️ `scopes`
+
+🔢 `security_scopes` 🔜 🆎 `SecurityScopes`.
+
+⚫️ 🔜 ✔️ 🏠 `scopes` ⏮️ 📇 ⚗ 🌐 ↔ ✔ ⚫️ & 🌐 🔗 👈 ⚙️ 👉 🎧-🔗. 👈 ⛓, 🌐 "⚓️"... 👉 💪 🔊 😨, ⚫️ 🔬 🔄 ⏪ 🔛.
+
+`security_scopes` 🎚 (🎓 `SecurityScopes`) 🚚 `scope_str` 🔢 ⏮️ 👁 🎻, 🔌 👈 ↔ 👽 🚀 (👥 🔜 ⚙️ ⚫️).
+
+👥 ✍ `HTTPException` 👈 👥 💪 🏤-⚙️ (`raise`) ⏪ 📚 ☝.
+
+👉 ⚠, 👥 🔌 ↔ 🚚 (🚥 🙆) 🎻 👽 🚀 (⚙️ `scope_str`). 👥 🚮 👈 🎻 ⚗ ↔ `WWW-Authenticate` 🎚 (👉 🍕 🔌).
+
+```Python hl_lines="105 107-115"
+{!../../../docs_src/security/tutorial005.py!}
+```
+
+## ✔ `username` & 💽 💠
+
+👥 ✔ 👈 👥 🤚 `username`, & ⚗ ↔.
+
+& ⤴️ 👥 ✔ 👈 📊 ⏮️ Pydantic 🏷 (✊ `ValidationError` ⚠), & 🚥 👥 🤚 ❌ 👂 🥙 🤝 ⚖️ ⚖ 📊 ⏮️ Pydantic, 👥 🤚 `HTTPException` 👥 ✍ ⏭.
+
+👈, 👥 ℹ Pydantic 🏷 `TokenData` ⏮️ 🆕 🏠 `scopes`.
+
+⚖ 📊 ⏮️ Pydantic 👥 💪 ⚒ 💭 👈 👥 ✔️, 🖼, ⚫️❔ `list` `str` ⏮️ ↔ & `str` ⏮️ `username`.
+
+↩️, 🖼, `dict`, ⚖️ 🕳 🙆, ⚫️ 💪 💔 🈸 ☝ ⏪, ⚒ ⚫️ 💂♂ ⚠.
+
+👥 ✔ 👈 👥 ✔️ 👩💻 ⏮️ 👈 🆔, & 🚥 🚫, 👥 🤚 👈 🎏 ⚠ 👥 ✍ ⏭.
+
+```Python hl_lines="46 116-127"
+{!../../../docs_src/security/tutorial005.py!}
+```
+
+## ✔ `scopes`
+
+👥 🔜 ✔ 👈 🌐 ↔ ✔, 👉 🔗 & 🌐 ⚓️ (🔌 *➡ 🛠️*), 🔌 ↔ 🚚 🤝 📨, ⏪ 🤚 `HTTPException`.
+
+👉, 👥 ⚙️ `security_scopes.scopes`, 👈 🔌 `list` ⏮️ 🌐 👫 ↔ `str`.
+
+```Python hl_lines="128-134"
+{!../../../docs_src/security/tutorial005.py!}
+```
+
+## 🔗 🌲 & ↔
+
+➡️ 📄 🔄 👉 🔗 🌲 & ↔.
+
+`get_current_active_user` 🔗 ✔️ 🎧-🔗 🔛 `get_current_user`, ↔ `"me"` 📣 `get_current_active_user` 🔜 🔌 📇 ✔ ↔ `security_scopes.scopes` 🚶♀️ `get_current_user`.
+
+*➡ 🛠️* ⚫️ 📣 ↔, `"items"`, 👉 🔜 📇 `security_scopes.scopes` 🚶♀️ `get_current_user`.
+
+📥 ❔ 🔗 🔗 & ↔ 👀 💖:
+
+* *➡ 🛠️* `read_own_items` ✔️:
+ * ✔ ↔ `["items"]` ⏮️ 🔗:
+ * `get_current_active_user`:
+ * 🔗 🔢 `get_current_active_user` ✔️:
+ * ✔ ↔ `["me"]` ⏮️ 🔗:
+ * `get_current_user`:
+ * 🔗 🔢 `get_current_user` ✔️:
+ * 🙅♂ ↔ ✔ ⚫️.
+ * 🔗 ⚙️ `oauth2_scheme`.
+ * `security_scopes` 🔢 🆎 `SecurityScopes`:
+ * 👉 `security_scopes` 🔢 ✔️ 🏠 `scopes` ⏮️ `list` ⚗ 🌐 👫 ↔ 📣 🔛,:
+ * `security_scopes.scopes` 🔜 🔌 `["me", "items"]` *➡ 🛠️* `read_own_items`.
+ * `security_scopes.scopes` 🔜 🔌 `["me"]` *➡ 🛠️* `read_users_me`, ↩️ ⚫️ 📣 🔗 `get_current_active_user`.
+ * `security_scopes.scopes` 🔜 🔌 `[]` (🕳) *➡ 🛠️* `read_system_status`, ↩️ ⚫️ 🚫 📣 🙆 `Security` ⏮️ `scopes`, & 🚮 🔗, `get_current_user`, 🚫 📣 🙆 `scope` 👯♂️.
+
+!!! tip
+ ⚠ & "🎱" 👜 📥 👈 `get_current_user` 🔜 ✔️ 🎏 📇 `scopes` ✅ 🔠 *➡ 🛠️*.
+
+ 🌐 ⚓️ 🔛 `scopes` 📣 🔠 *➡ 🛠️* & 🔠 🔗 🔗 🌲 👈 🎯 *➡ 🛠️*.
+
+## 🌖 ℹ 🔃 `SecurityScopes`
+
+👆 💪 ⚙️ `SecurityScopes` 🙆 ☝, & 💗 🥉, ⚫️ 🚫 ✔️ "🌱" 🔗.
+
+⚫️ 🔜 🕧 ✔️ 💂♂ ↔ 📣 ⏮️ `Security` 🔗 & 🌐 ⚓️ **👈 🎯** *➡ 🛠️* & **👈 🎯** 🔗 🌲.
+
+↩️ `SecurityScopes` 🔜 ✔️ 🌐 ↔ 📣 ⚓️, 👆 💪 ⚙️ ⚫️ ✔ 👈 🤝 ✔️ 🚚 ↔ 🇨🇫 🔗 🔢, & ⤴️ 📣 🎏 ↔ 📄 🎏 *➡ 🛠️*.
+
+👫 🔜 ✅ ➡ 🔠 *➡ 🛠️*.
+
+## ✅ ⚫️
+
+🚥 👆 📂 🛠️ 🩺, 👆 💪 🔓 & ✔ ❔ ↔ 👆 💚 ✔.
+
+
+
+🚥 👆 🚫 🖊 🙆 ↔, 👆 🔜 "🔓", ✋️ 🕐❔ 👆 🔄 🔐 `/users/me/` ⚖️ `/users/me/items/` 👆 🔜 🤚 ❌ 💬 👈 👆 🚫 ✔️ 🥃 ✔. 👆 🔜 💪 🔐 `/status/`.
+
+& 🚥 👆 🖊 ↔ `me` ✋️ 🚫 ↔ `items`, 👆 🔜 💪 🔐 `/users/me/` ✋️ 🚫 `/users/me/items/`.
+
+👈 ⚫️❔ 🔜 🔨 🥉 🥳 🈸 👈 🔄 🔐 1️⃣ 👫 *➡ 🛠️* ⏮️ 🤝 🚚 👩💻, ⚓️ 🔛 ❔ 📚 ✔ 👩💻 🤝 🈸.
+
+## 🔃 🥉 🥳 🛠️
+
+👉 🖼 👥 ⚙️ Oauth2️⃣ "🔐" 💧.
+
+👉 ☑ 🕐❔ 👥 🚨 👆 👍 🈸, 🎲 ⏮️ 👆 👍 🕸.
+
+↩️ 👥 💪 💙 ⚫️ 📨 `username` & `password`, 👥 🎛 ⚫️.
+
+✋️ 🚥 👆 🏗 Oauth2️⃣ 🈸 👈 🎏 🔜 🔗 (➡, 🚥 👆 🏗 🤝 🐕🦺 🌓 👱📔, 🇺🇸🔍, 📂, ♒️.) 👆 🔜 ⚙️ 1️⃣ 🎏 💧.
+
+🌅 ⚠ 🔑 💧.
+
+🏆 🔐 📟 💧, ✋️ 🌖 🏗 🛠️ ⚫️ 🚚 🌅 📶. ⚫️ 🌅 🏗, 📚 🐕🦺 🔚 🆙 ✔ 🔑 💧.
+
+!!! note
+ ⚫️ ⚠ 👈 🔠 🤝 🐕🦺 📛 👫 💧 🎏 🌌, ⚒ ⚫️ 🍕 👫 🏷.
+
+ ✋️ 🔚, 👫 🛠️ 🎏 Oauth2️⃣ 🐩.
+
+**FastAPI** 🔌 🚙 🌐 👫 Oauth2️⃣ 🤝 💧 `fastapi.security.oauth2`.
+
+## `Security` 👨🎨 `dependencies`
+
+🎏 🌌 👆 💪 🔬 `list` `Depends` 👨🎨 `dependencies` 🔢 (🔬 [🔗 ➡ 🛠️ 👨🎨](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}), 👆 💪 ⚙️ `Security` ⏮️ `scopes` 📤.
diff --git a/docs/em/docs/advanced/settings.md b/docs/em/docs/advanced/settings.md
new file mode 100644
index 000000000..bc50bf755
--- /dev/null
+++ b/docs/em/docs/advanced/settings.md
@@ -0,0 +1,382 @@
+# ⚒ & 🌐 🔢
+
+📚 💼 👆 🈸 💪 💪 🔢 ⚒ ⚖️ 📳, 🖼 ㊙ 🔑, 💽 🎓, 🎓 📧 🐕🦺, ♒️.
+
+🏆 👫 ⚒ 🔢 (💪 🔀), 💖 💽 📛. & 📚 💪 🚿, 💖 ㊙.
+
+👉 🤔 ⚫️ ⚠ 🚚 👫 🌐 🔢 👈 ✍ 🈸.
+
+## 🌐 🔢
+
+!!! tip
+ 🚥 👆 ⏪ 💭 ⚫️❔ "🌐 🔢" & ❔ ⚙️ 👫, 💭 🆓 🚶 ⏭ 📄 🔛.
+
+🌐 🔢 (💭 "🇨🇻 {") 🔢 👈 🖖 🏞 🐍 📟, 🏃♂ ⚙️, & 💪 ✍ 👆 🐍 📟 (⚖️ 🎏 📋 👍).
+
+👆 💪 ✍ & ⚙️ 🌐 🔢 🐚, 🍵 💆♂ 🐍:
+
+=== "💾, 🇸🇻, 🚪 🎉"
+
+
+
+& ⤴️, 📂 🩺 🎧-🈸, http://127.0.0.1:8000/subapi/docs.
+
+👆 🔜 👀 🏧 🛠️ 🩺 🎧-🈸, ✅ 🕴 🚮 👍 _➡ 🛠️_, 🌐 🔽 ☑ 🎧-➡ 🔡 `/subapi`:
+
+
+
+🚥 👆 🔄 🔗 ⏮️ 🙆 2️⃣ 👩💻 🔢, 👫 🔜 👷 ☑, ↩️ 🖥 🔜 💪 💬 🔠 🎯 📱 ⚖️ 🎧-📱.
+
+### 📡 ℹ: `root_path`
+
+🕐❔ 👆 🗻 🎧-🈸 🔬 🔛, FastAPI 🔜 ✊ 💅 🔗 🗻 ➡ 🎧-🈸 ⚙️ 🛠️ ⚪️➡️ 🔫 🔧 🤙 `root_path`.
+
+👈 🌌, 🎧-🈸 🔜 💭 ⚙️ 👈 ➡ 🔡 🩺 🎚.
+
+& 🎧-🈸 💪 ✔️ 🚮 👍 📌 🎧-🈸 & 🌐 🔜 👷 ☑, ↩️ FastAPI 🍵 🌐 👉 `root_path`Ⓜ 🔁.
+
+👆 🔜 💡 🌅 🔃 `root_path` & ❔ ⚙️ ⚫️ 🎯 📄 🔃 [⛅ 🗳](./behind-a-proxy.md){.internal-link target=_blank}.
diff --git a/docs/em/docs/advanced/templates.md b/docs/em/docs/advanced/templates.md
new file mode 100644
index 000000000..1fb57725a
--- /dev/null
+++ b/docs/em/docs/advanced/templates.md
@@ -0,0 +1,77 @@
+# 📄
+
+👆 💪 ⚙️ 🙆 📄 🚒 👆 💚 ⏮️ **FastAPI**.
+
+⚠ ⚒ Jinja2️⃣, 🎏 1️⃣ ⚙️ 🏺 & 🎏 🧰.
+
+📤 🚙 🔗 ⚫️ 💪 👈 👆 💪 ⚙️ 🔗 👆 **FastAPI** 🈸 (🚚 💃).
+
+## ❎ 🔗
+
+❎ `jinja2`:
+
+
+
+👆 💪 🆎 📧 🔢 📦, & 📨 👫:
+
+
+
+& 👆 **FastAPI** 🈸 ⏮️ *️⃣ 🔜 📨 🔙:
+
+
+
+👆 💪 📨 (& 📨) 📚 📧:
+
+
+
+& 🌐 👫 🔜 ⚙️ 🎏 *️⃣ 🔗.
+
+## ⚙️ `Depends` & 🎏
+
+*️⃣ 🔗 👆 💪 🗄 ⚪️➡️ `fastapi` & ⚙️:
+
+* `Depends`
+* `Security`
+* `Cookie`
+* `Header`
+* `Path`
+* `Query`
+
+👫 👷 🎏 🌌 🎏 FastAPI 🔗/*➡ 🛠️*:
+
+```Python hl_lines="66-77 76-91"
+{!../../../docs_src/websockets/tutorial002.py!}
+```
+
+!!! info
+ 👉 *️⃣ ⚫️ 🚫 🤙 ⚒ 🔑 🤚 `HTTPException`, ↩️ 👥 🤚 `WebSocketException`.
+
+ 👆 💪 ⚙️ 📪 📟 ⚪️➡️ ☑ 📟 🔬 🔧.
+
+### 🔄 *️⃣ ⏮️ 🔗
+
+🚥 👆 📁 📛 `main.py`, 🏃 👆 🈸 ⏮️:
+
+
+
+## 🚚 🔀 & 💗 👩💻
+
+🕐❔ *️⃣ 🔗 📪, `await websocket.receive_text()` 🔜 🤚 `WebSocketDisconnect` ⚠, ❔ 👆 💪 ⤴️ ✊ & 🍵 💖 👉 🖼.
+
+```Python hl_lines="81-83"
+{!../../../docs_src/websockets/tutorial003.py!}
+```
+
+🔄 ⚫️ 👅:
+
+* 📂 📱 ⏮️ 📚 🖥 📑.
+* ✍ 📧 ⚪️➡️ 👫.
+* ⤴️ 🔐 1️⃣ 📑.
+
+👈 🔜 🤚 `WebSocketDisconnect` ⚠, & 🌐 🎏 👩💻 🔜 📨 📧 💖:
+
+```
+Client #1596980209979 left the chat
+```
+
+!!! tip
+ 📱 🔛 ⭐ & 🙅 🖼 🎦 ❔ 🍵 & 📻 📧 📚 *️⃣ 🔗.
+
+ ✋️ ✔️ 🤯 👈, 🌐 🍵 💾, 👁 📇, ⚫️ 🔜 🕴 👷 ⏪ 🛠️ 🏃, & 🔜 🕴 👷 ⏮️ 👁 🛠️.
+
+ 🚥 👆 💪 🕳 ⏩ 🛠️ ⏮️ FastAPI ✋️ 👈 🌖 🏋️, 🐕🦺 ✳, ✳ ⚖️ 🎏, ✅ 🗜/📻.
+
+## 🌅 ℹ
+
+💡 🌅 🔃 🎛, ✅ 💃 🧾:
+
+* `WebSocket` 🎓.
+* 🎓-⚓️ *️⃣ 🚚.
diff --git a/docs/em/docs/advanced/wsgi.md b/docs/em/docs/advanced/wsgi.md
new file mode 100644
index 000000000..4d051807f
--- /dev/null
+++ b/docs/em/docs/advanced/wsgi.md
@@ -0,0 +1,37 @@
+# ✅ 🇨🇻 - 🏺, ✳, 🎏
+
+👆 💪 🗻 🇨🇻 🈸 👆 👀 ⏮️ [🎧 🈸 - 🗻](./sub-applications.md){.internal-link target=_blank}, [⛅ 🗳](./behind-a-proxy.md){.internal-link target=_blank}.
+
+👈, 👆 💪 ⚙️ `WSGIMiddleware` & ⚙️ ⚫️ 🎁 👆 🇨🇻 🈸, 🖼, 🏺, ✳, ♒️.
+
+## ⚙️ `WSGIMiddleware`
+
+👆 💪 🗄 `WSGIMiddleware`.
+
+⤴️ 🎁 🇨🇻 (✅ 🏺) 📱 ⏮️ 🛠️.
+
+& ⤴️ 🗻 👈 🔽 ➡.
+
+```Python hl_lines="2-3 22"
+{!../../../docs_src/wsgi/tutorial001.py!}
+```
+
+## ✅ ⚫️
+
+🔜, 🔠 📨 🔽 ➡ `/v1/` 🔜 🍵 🏺 🈸.
+
+& 🎂 🔜 🍵 **FastAPI**.
+
+🚥 👆 🏃 ⚫️ ⏮️ Uvicorn & 🚶 http://localhost:8000/v1/ 👆 🔜 👀 📨 ⚪️➡️ 🏺:
+
+```txt
+Hello, World from Flask!
+```
+
+& 🚥 👆 🚶 http://localhost:8000/v2 👆 🔜 👀 📨 ⚪️➡️ FastAPI:
+
+```JSON
+{
+ "message": "Hello World"
+}
+```
diff --git a/docs/em/docs/alternatives.md b/docs/em/docs/alternatives.md
new file mode 100644
index 000000000..6169aa52d
--- /dev/null
+++ b/docs/em/docs/alternatives.md
@@ -0,0 +1,414 @@
+# 🎛, 🌈 & 🔺
+
+⚫️❔ 😮 **FastAPI**, ❔ ⚫️ 🔬 🎏 🎛 & ⚫️❔ ⚫️ 🇭🇲 ⚪️➡️ 👫.
+
+## 🎶
+
+**FastAPI** 🚫🔜 🔀 🚥 🚫 ⏮️ 👷 🎏.
+
+📤 ✔️ 📚 🧰 ✍ ⏭ 👈 ✔️ ℹ 😮 🚮 🏗.
+
+👤 ✔️ ❎ 🏗 🆕 🛠️ 📚 1️⃣2️⃣🗓️. 🥇 👤 🔄 ❎ 🌐 ⚒ 📔 **FastAPI** ⚙️ 📚 🎏 🛠️, 🔌-🔌, & 🧰.
+
+✋️ ☝, 📤 🙅♂ 🎏 🎛 🌘 🏗 🕳 👈 🚚 🌐 👫 ⚒, ✊ 🏆 💭 ⚪️➡️ ⏮️ 🧰, & 🌀 👫 🏆 🌌 💪, ⚙️ 🇪🇸 ⚒ 👈 ➖🚫 💪 ⏭ (🐍 3️⃣.6️⃣ ➕ 🆎 🔑).
+
+## ⏮️ 🧰
+
+### ✳
+
+⚫️ 🌅 🌟 🐍 🛠️ & 🛎 🕴. ⚫️ ⚙️ 🏗 ⚙️ 💖 👱📔.
+
+⚫️ 📶 😆 🔗 ⏮️ 🔗 💽 (💖 ✳ ⚖️ ✳),, ✔️ ☁ 💽 (💖 🗄, ✳, 👸, ♒️) 👑 🏪 🚒 🚫 📶 ⏩.
+
+⚫️ ✍ 🏗 🕸 👩💻, 🚫 ✍ 🔗 ⚙️ 🏛 🕸 (💖 😥, Vue.js & 📐) ⚖️ 🎏 ⚙️ (💖 ☁ 📳) 🔗 ⏮️ ⚫️.
+
+### ✳ 🎂 🛠️
+
+✳ 🎂 🛠️ ✍ 🗜 🧰 🏗 🕸 🔗 ⚙️ ✳ 🔘, 📉 🚮 🛠️ 🛠️.
+
+⚫️ ⚙️ 📚 🏢 ✅ 🦎, 🟥 👒 & 🎟.
+
+⚫️ 🕐 🥇 🖼 **🏧 🛠️ 🧾**, & 👉 🎯 🕐 🥇 💭 👈 😮 "🔎" **FastAPI**.
+
+!!! note
+ ✳ 🎂 🛠️ ✍ ✡ 🇺🇸🏛. 🎏 👼 💃 & Uvicorn, 🔛 ❔ **FastAPI** ⚓️.
+
+
+!!! check "😮 **FastAPI** "
+ ✔️ 🏧 🛠️ 🧾 🕸 👩💻 🔢.
+
+### 🏺
+
+🏺 "🕸", ⚫️ 🚫 🔌 💽 🛠️ 🚫 📚 👜 👈 👟 🔢 ✳.
+
+👉 🦁 & 💪 ✔ 🔨 👜 💖 ⚙️ ☁ 💽 👑 💽 💾 ⚙️.
+
+⚫️ 📶 🙅, ⚫️ 📶 🏋️ 💡, 👐 🧾 🤚 🙁 📡 ☝.
+
+⚫️ 🛎 ⚙️ 🎏 🈸 👈 🚫 🎯 💪 💽, 👩💻 🧾, ⚖️ 🙆 📚 ⚒ 👈 👟 🏤-🏗 ✳. 👐 📚 👫 ⚒ 💪 🚮 ⏮️ 🔌-🔌.
+
+👉 ⚖ 🍕, & ➖ "🕸" 👈 💪 ↔ 📔 ⚫️❔ ⚫️❔ 💪 🔑 ⚒ 👈 👤 💚 🚧.
+
+👐 🦁 🏺, ⚫️ 😑 💖 👍 🏏 🏗 🔗. ⏭ 👜 🔎 "✳ 🎂 🛠️" 🏺.
+
+!!! check "😮 **FastAPI** "
+ ◾-🛠️. ⚒ ⚫️ ⏩ 🌀 & 🏏 🧰 & 🍕 💪.
+
+ ✔️ 🙅 & ⏩ ⚙️ 🕹 ⚙️.
+
+
+### 📨
+
+**FastAPI** 🚫 🤙 🎛 **📨**. 👫 ↔ 📶 🎏.
+
+⚫️ 🔜 🤙 ⚠ ⚙️ 📨 *🔘* FastAPI 🈸.
+
+✋️, FastAPI 🤚 🌈 ⚪️➡️ 📨.
+
+**📨** 🗃 *🔗* ⏮️ 🔗 (👩💻), ⏪ **FastAPI** 🗃 *🏗* 🔗 (💽).
+
+👫, 🌖 ⚖️ 🌘, 🔄 🔚, 🔗 🔠 🎏.
+
+📨 ✔️ 📶 🙅 & 🏋️ 🔧, ⚫️ 📶 ⏩ ⚙️, ⏮️ 🤔 🔢. ✋️ 🎏 🕰, ⚫️ 📶 🏋️ & 🛃.
+
+👈 ⚫️❔, 💬 🛂 🕸:
+
+> 📨 1️⃣ 🏆 ⏬ 🐍 📦 🌐 🕰
+
+🌌 👆 ⚙️ ⚫️ 📶 🙅. 🖼, `GET` 📨, 👆 🔜 ✍:
+
+```Python
+response = requests.get("http://example.com/some/url")
+```
+
+FastAPI 😑 🛠️ *➡ 🛠️* 💪 👀 💖:
+
+```Python hl_lines="1"
+@app.get("/some/url")
+def read_url():
+ return {"message": "Hello World"}
+```
+
+👀 🔀 `requests.get(...)` & `@app.get(...)`.
+
+!!! check "😮 **FastAPI** "
+ * ✔️ 🙅 & 🏋️ 🛠️.
+ * ⚙️ 🇺🇸🔍 👩🔬 📛 (🛠️) 🔗, 🎯 & 🏋️ 🌌.
+ * ✔️ 🤔 🔢, ✋️ 🏋️ 🛃.
+
+
+### 🦁 / 🗄
+
+👑 ⚒ 👤 💚 ⚪️➡️ ✳ 🎂 🛠️ 🏧 🛠️ 🧾.
+
+⤴️ 👤 🔎 👈 📤 🐩 📄 🔗, ⚙️ 🎻 (⚖️ 📁, ↔ 🎻) 🤙 🦁.
+
+& 📤 🕸 👩💻 🔢 🦁 🛠️ ⏪ ✍. , 💆♂ 💪 🏗 🦁 🧾 🛠️ 🔜 ✔ ⚙️ 👉 🕸 👩💻 🔢 🔁.
+
+☝, 🦁 👐 💾 🏛, 📁 🗄.
+
+👈 ⚫️❔ 🕐❔ 💬 🔃 ⏬ 2️⃣.0️⃣ ⚫️ ⚠ 💬 "🦁", & ⏬ 3️⃣ ➕ "🗄".
+
+!!! check "😮 **FastAPI** "
+ 🛠️ & ⚙️ 📂 🐩 🛠️ 🔧, ↩️ 🛃 🔗.
+
+ & 🛠️ 🐩-⚓️ 👩💻 🔢 🧰:
+
+ * 🦁 🎚
+ * 📄
+
+ 👫 2️⃣ 👐 ➖ 📶 🌟 & ⚖, ✋️ 🔨 ⏩ 🔎, 👆 💪 🔎 💯 🌖 🎛 👩💻 🔢 🗄 (👈 👆 💪 ⚙️ ⏮️ **FastAPI**).
+
+### 🏺 🎂 🛠️
+
+📤 📚 🏺 🎂 🛠️, ✋️ ⏮️ 💰 🕰 & 👷 🔘 🔬 👫, 👤 🔎 👈 📚 😞 ⚖️ 🚫, ⏮️ 📚 🧍 ❔ 👈 ⚒ 👫 🙃.
+
+### 🍭
+
+1️⃣ 👑 ⚒ 💪 🛠️ ⚙️ 📊 "🛠️" ❔ ✊ 📊 ⚪️➡️ 📟 (🐍) & 🏭 ⚫️ 🔘 🕳 👈 💪 📨 🔘 🕸. 🖼, 🏭 🎚 ⚗ 📊 ⚪️➡️ 💽 🔘 🎻 🎚. 🏭 `datetime` 🎚 🔘 🎻, ♒️.
+
+➕1️⃣ 🦏 ⚒ 💚 🔗 💽 🔬, ⚒ 💭 👈 💽 ☑, 🤝 🎯 🔢. 🖼, 👈 🏑 `int`, & 🚫 🎲 🎻. 👉 ✴️ ⚠ 📨 💽.
+
+🍵 💽 🔬 ⚙️, 👆 🔜 ✔️ 🌐 ✅ ✋, 📟.
+
+👫 ⚒ ⚫️❔ 🍭 🏗 🚚. ⚫️ 👑 🗃, & 👤 ✔️ ⚙️ ⚫️ 📚 ⏭.
+
+✋️ ⚫️ ✍ ⏭ 📤 🔀 🐍 🆎 🔑. , 🔬 🔠 🔗 👆 💪 ⚙️ 🎯 🇨🇻 & 🎓 🚚 🍭.
+
+!!! check "😮 **FastAPI** "
+ ⚙️ 📟 🔬 "🔗" 👈 🚚 💽 🆎 & 🔬, 🔁.
+
+### Webarg
+
+➕1️⃣ 🦏 ⚒ ✔ 🔗 ✍ 📊 ⚪️➡️ 📨 📨.
+
+Webarg 🧰 👈 ⚒ 🚚 👈 🔛 🔝 📚 🛠️, 🔌 🏺.
+
+⚫️ ⚙️ 🍭 🔘 💽 🔬. & ⚫️ ✍ 🎏 👩💻.
+
+⚫️ 👑 🧰 & 👤 ✔️ ⚙️ ⚫️ 📚 💁♂️, ⏭ ✔️ **FastAPI**.
+
+!!! info
+ Webarg ✍ 🎏 🍭 👩💻.
+
+!!! check "😮 **FastAPI** "
+ ✔️ 🏧 🔬 📨 📨 💽.
+
+### APISpec
+
+🍭 & Webarg 🚚 🔬, ✍ & 🛠️ 🔌-🔌.
+
+✋️ 🧾 ❌. ⤴️ APISpec ✍.
+
+⚫️ 🔌-📚 🛠️ (& 📤 🔌-💃 💁♂️).
+
+🌌 ⚫️ 👷 👈 👆 ✍ 🔑 🔗 ⚙️ 📁 📁 🔘 #️⃣ 🔠 🔢 🚚 🛣.
+
+& ⚫️ 🏗 🗄 🔗.
+
+👈 ❔ ⚫️ 👷 🏺, 💃, 🆘, ♒️.
+
+✋️ ⤴️, 👥 ✔️ 🔄 ⚠ ✔️ ◾-❕, 🔘 🐍 🎻 (🦏 📁).
+
+👨🎨 💪 🚫 ℹ 🌅 ⏮️ 👈. & 🚥 👥 🔀 🔢 ⚖️ 🍭 🔗 & 💭 🔀 👈 📁#️⃣, 🏗 🔗 🔜 ❌.
+
+!!! info
+ APISpec ✍ 🎏 🍭 👩💻.
+
+
+!!! check "😮 **FastAPI** "
+ 🐕🦺 📂 🐩 🛠️, 🗄.
+
+### 🏺-Apispec
+
+⚫️ 🏺 🔌 -, 👈 👔 👯♂️ Webarg, 🍭 & APISpec.
+
+⚫️ ⚙️ ℹ ⚪️➡️ Webarg & 🍭 🔁 🏗 🗄 🔗, ⚙️ APISpec.
+
+⚫️ 👑 🧰, 📶 🔽-📈. ⚫️ 🔜 🌌 🌖 🌟 🌘 📚 🏺 🔌-🔌 👅 📤. ⚫️ 💪 ↩️ 🚮 🧾 ➖ 💁♂️ 🩲 & 📝.
+
+👉 ❎ ✔️ ✍ 📁 (➕1️⃣ ❕) 🔘 🐍 ✍.
+
+👉 🌀 🏺, 🏺-Apispec ⏮️ 🍭 & Webarg 👇 💕 👩💻 📚 ⏭ 🏗 **FastAPI**.
+
+⚙️ ⚫️ ↘️ 🏗 📚 🏺 🌕-📚 🚂. 👫 👑 📚 👤 (& 📚 🔢 🏉) ✔️ ⚙️ 🆙 🔜:
+
+* https://github.com/tiangolo/full-stack
+* https://github.com/tiangolo/full-stack-flask-couchbase
+* https://github.com/tiangolo/full-stack-flask-couchdb
+
+& 👫 🎏 🌕-📚 🚂 🧢 [**FastAPI** 🏗 🚂](project-generation.md){.internal-link target=_blank}.
+
+!!! info
+ 🏺-Apispec ✍ 🎏 🍭 👩💻.
+
+!!! check "😮 **FastAPI** "
+ 🏗 🗄 🔗 🔁, ⚪️➡️ 🎏 📟 👈 🔬 🛠️ & 🔬.
+
+### NestJS (& 📐)
+
+👉 ➖🚫 🚫 🐍, NestJS 🕸 (📕) ✳ 🛠️ 😮 📐.
+
+⚫️ 🏆 🕳 🙁 🎏 ⚫️❔ 💪 🔨 ⏮️ 🏺-Apispec.
+
+⚫️ ✔️ 🛠️ 🔗 💉 ⚙️, 😮 📐 2️⃣. ⚫️ 🚚 🏤-® "💉" (💖 🌐 🎏 🔗 💉 ⚙️ 👤 💭),, ⚫️ 🚮 🎭 & 📟 🔁.
+
+🔢 🔬 ⏮️ 📕 🆎 (🎏 🐍 🆎 🔑), 👨🎨 🐕🦺 👍.
+
+✋️ 📕 📊 🚫 🛡 ⏮️ 📹 🕸, ⚫️ 🚫🔜 ⚓️ 🔛 🆎 🔬 🔬, 🛠️ & 🧾 🎏 🕰. ↩️ 👉 & 🔧 🚫, 🤚 🔬, 🛠️ & 🏧 🔗 ⚡, ⚫️ 💪 🚮 👨🎨 📚 🥉. , ⚫️ ▶️️ 🔁.
+
+⚫️ 💪 🚫 🍵 🔁 🏷 📶 👍. , 🚥 🎻 💪 📨 🎻 🎚 👈 ✔️ 🔘 🏑 👈 🔄 🐦 🎻 🎚, ⚫️ 🚫🔜 ☑ 📄 & ✔.
+
+!!! check "😮 **FastAPI** "
+ ⚙️ 🐍 🆎 ✔️ 👑 👨🎨 🐕🦺.
+
+ ✔️ 🏋️ 🔗 💉 ⚙️. 🔎 🌌 📉 📟 🔁.
+
+### 🤣
+
+⚫️ 🕐 🥇 📶 ⏩ 🐍 🛠️ ⚓️ 🔛 `asyncio`. ⚫️ ⚒ 📶 🎏 🏺.
+
+!!! note "📡 ℹ"
+ ⚫️ ⚙️ `uvloop` ↩️ 🔢 🐍 `asyncio` ➰. 👈 ⚫️❔ ⚒ ⚫️ ⏩.
+
+ ⚫️ 🎯 😮 Uvicorn & 💃, 👈 ⏳ ⏩ 🌘 🤣 📂 📇.
+
+!!! check "😮 **FastAPI** "
+ 🔎 🌌 ✔️ 😜 🎭.
+
+ 👈 ⚫️❔ **FastAPI** ⚓️ 🔛 💃, ⚫️ ⏩ 🛠️ 💪 (💯 🥉-🥳 📇).
+
+### 🦅
+
+🦅 ➕1️⃣ ↕ 🎭 🐍 🛠️, ⚫️ 🔧 ⭐, & 👷 🏛 🎏 🛠️ 💖 🤗.
+
+⚫️ 🏗 ✔️ 🔢 👈 📨 2️⃣ 🔢, 1️⃣ "📨" & 1️⃣ "📨". ⤴️ 👆 "✍" 🍕 ⚪️➡️ 📨, & "✍" 🍕 📨. ↩️ 👉 🔧, ⚫️ 🚫 💪 📣 📨 🔢 & 💪 ⏮️ 🐩 🐍 🆎 🔑 🔢 🔢.
+
+, 💽 🔬, 🛠️, & 🧾, ✔️ ⌛ 📟, 🚫 🔁. ⚖️ 👫 ✔️ 🛠️ 🛠️ 🔛 🔝 🦅, 💖 🤗. 👉 🎏 🔺 🔨 🎏 🛠️ 👈 😮 🦅 🔧, ✔️ 1️⃣ 📨 🎚 & 1️⃣ 📨 🎚 🔢.
+
+!!! check "😮 **FastAPI** "
+ 🔎 🌌 🤚 👑 🎭.
+
+ ⤴️ ⏮️ 🤗 (🤗 ⚓️ 🔛 🦅) 😮 **FastAPI** 📣 `response` 🔢 🔢.
+
+ 👐 FastAPI ⚫️ 📦, & ⚙️ ✴️ ⚒ 🎚, 🍪, & 🎛 👔 📟.
+
+### ♨
+
+👤 🔎 ♨ 🥇 ▶️ 🏗 **FastAPI**. & ⚫️ ✔️ 🎏 💭:
+
+* ⚓️ 🔛 🐍 🆎 🔑.
+* 🔬 & 🧾 ⚪️➡️ 👫 🆎.
+* 🔗 💉 ⚙️.
+
+⚫️ 🚫 ⚙️ 💽 🔬, 🛠️ & 🧾 🥉-🥳 🗃 💖 Pydantic, ⚫️ ✔️ 🚮 👍. , 👫 💽 🆎 🔑 🔜 🚫 ♻ 💪.
+
+⚫️ 🚚 🐥 🍖 🌅 🔁 📳. & ⚫️ ⚓️ 🔛 🇨🇻 (↩️ 🔫), ⚫️ 🚫 🔧 ✊ 📈 ↕-🎭 🚚 🧰 💖 Uvicorn, 💃 & 🤣.
+
+🔗 💉 ⚙️ 🚚 🏤-® 🔗 & 🔗 ❎ 🧢 🔛 📣 🆎. , ⚫️ 🚫 💪 📣 🌅 🌘 1️⃣ "🦲" 👈 🚚 🎯 🆎.
+
+🛣 📣 👁 🥉, ⚙️ 🔢 📣 🎏 🥉 (↩️ ⚙️ 👨🎨 👈 💪 🥉 ▶️️ 🔛 🔝 🔢 👈 🍵 🔗). 👉 🔐 ❔ ✳ 🔨 ⚫️ 🌘 ❔ 🏺 (& 💃) 🔨 ⚫️. ⚫️ 🎏 📟 👜 👈 📶 😆 🔗.
+
+!!! check "😮 **FastAPI** "
+ 🔬 ➕ 🔬 💽 🆎 ⚙️ "🔢" 💲 🏷 🔢. 👉 📉 👨🎨 🐕🦺, & ⚫️ 🚫 💪 Pydantic ⏭.
+
+ 👉 🤙 😮 🛠️ 🍕 Pydantic, 🐕🦺 🎏 🔬 📄 👗 (🌐 👉 🛠️ 🔜 ⏪ 💪 Pydantic).
+
+### 🤗
+
+🤗 🕐 🥇 🛠️ 🛠️ 📄 🛠️ 🔢 🆎 ⚙️ 🐍 🆎 🔑. 👉 👑 💭 👈 😮 🎏 🧰 🎏.
+
+⚫️ ⚙️ 🛃 🆎 🚮 📄 ↩️ 🐩 🐍 🆎, ✋️ ⚫️ 🦏 🔁 ⏩.
+
+⚫️ 🕐 🥇 🛠️ 🏗 🛃 🔗 📣 🎂 🛠️ 🎻.
+
+⚫️ 🚫 ⚓️ 🔛 🐩 💖 🗄 & 🎻 🔗. ⚫️ 🚫🔜 🎯 🛠️ ⚫️ ⏮️ 🎏 🧰, 💖 🦁 🎚. ✋️ 🔄, ⚫️ 📶 💡 💭.
+
+⚫️ ✔️ 😌, ⭐ ⚒: ⚙️ 🎏 🛠️, ⚫️ 💪 ✍ 🔗 & 🇳🇨.
+
+⚫️ ⚓️ 🔛 ⏮️ 🐩 🔁 🐍 🕸 🛠️ (🇨🇻), ⚫️ 💪 🚫 🍵 *️⃣ & 🎏 👜, 👐 ⚫️ ✔️ ↕ 🎭 💁♂️.
+
+!!! info
+ 🤗 ✍ ✡ 🗄, 🎏 👼 `isort`, 👑 🧰 🔁 😇 🗄 🐍 📁.
+
+!!! check "💭 😮 **FastAPI**"
+ 🤗 😮 🍕 APIStar, & 1️⃣ 🧰 👤 🔎 🏆 👍, 🌟 APIStar.
+
+ 🤗 ℹ 😍 **FastAPI** ⚙️ 🐍 🆎 🔑 📣 🔢, & 🏗 🔗 ⚖ 🛠️ 🔁.
+
+ 🤗 😮 **FastAPI** 📣 `response` 🔢 🔢 ⚒ 🎚 & 🍪.
+
+### APIStar (<= 0️⃣.5️⃣)
+
+▶️️ ⏭ 🤔 🏗 **FastAPI** 👤 🔎 **APIStar** 💽. ⚫️ ✔️ 🌖 🌐 👤 👀 & ✔️ 👑 🔧.
+
+⚫️ 🕐 🥇 🛠️ 🛠️ ⚙️ 🐍 🆎 🔑 📣 🔢 & 📨 👈 👤 ⏱ 👀 (⏭ NestJS & ♨). 👤 🔎 ⚫️ 🌅 ⚖️ 🌘 🎏 🕰 🤗. ✋️ APIStar ⚙️ 🗄 🐩.
+
+⚫️ ✔️ 🏧 💽 🔬, 💽 🛠️ & 🗄 🔗 ⚡ ⚓️ 🔛 🎏 🆎 🔑 📚 🥉.
+
+💪 🔗 🔑 🚫 ⚙️ 🎏 🐍 🆎 🔑 💖 Pydantic, ⚫️ 🍖 🌅 🎏 🍭,, 👨🎨 🐕🦺 🚫🔜 👍, ✋️, APIStar 🏆 💪 🎛.
+
+⚫️ ✔️ 🏆 🎭 📇 🕰 (🕴 💥 💃).
+
+🥇, ⚫️ 🚫 ✔️ 🏧 🛠️ 🧾 🕸 🎚, ✋️ 👤 💭 👤 💪 🚮 🦁 🎚 ⚫️.
+
+⚫️ ✔️ 🔗 💉 ⚙️. ⚫️ ✔ 🏤-® 🦲, 🎏 🧰 🔬 🔛. ✋️, ⚫️ 👑 ⚒.
+
+👤 🙅 💪 ⚙️ ⚫️ 🌕 🏗, ⚫️ 🚫 ✔️ 💂♂ 🛠️,, 👤 🚫 🚫 ❎ 🌐 ⚒ 👤 ✔️ ⏮️ 🌕-📚 🚂 ⚓️ 🔛 🏺-Apispec. 👤 ✔️ 👇 📈 🏗 ✍ 🚲 📨 ❎ 👈 🛠️.
+
+✋️ ⤴️, 🏗 🎯 🔀.
+
+⚫️ 🙅♂ 📏 🛠️ 🕸 🛠️, 👼 💪 🎯 🔛 💃.
+
+🔜 APIStar ⚒ 🧰 ✔ 🗄 🔧, 🚫 🕸 🛠️.
+
+!!! info
+ APIStar ✍ ✡ 🇺🇸🏛. 🎏 👨 👈 ✍:
+
+ * ✳ 🎂 🛠️
+ * 💃 (❔ **FastAPI** ⚓️)
+ * Uvicorn (⚙️ 💃 & **FastAPI**)
+
+!!! check "😮 **FastAPI** "
+ 🔀.
+
+ 💭 📣 💗 👜 (💽 🔬, 🛠️ & 🧾) ⏮️ 🎏 🐍 🆎, 👈 🎏 🕰 🚚 👑 👨🎨 🐕🦺, 🕳 👤 🤔 💎 💭.
+
+ & ⏮️ 🔎 📏 🕰 🎏 🛠️ & 🔬 📚 🎏 🎛, APIStar 🏆 🎛 💪.
+
+ ⤴️ APIStar ⛔️ 🔀 💽 & 💃 ✍, & 🆕 👻 🏛 ✅ ⚙️. 👈 🏁 🌈 🏗 **FastAPI**.
+
+ 👤 🤔 **FastAPI** "🛐 👨💼" APIStar, ⏪ 📉 & 📈 ⚒, ⌨ ⚙️, & 🎏 🍕, ⚓️ 🔛 🏫 ⚪️➡️ 🌐 👉 ⏮️ 🧰.
+
+## ⚙️ **FastAPI**
+
+### Pydantic
+
+Pydantic 🗃 🔬 💽 🔬, 🛠️ & 🧾 (⚙️ 🎻 🔗) ⚓️ 🔛 🐍 🆎 🔑.
+
+👈 ⚒ ⚫️ 📶 🏋️.
+
+⚫️ ⭐ 🍭. 👐 ⚫️ ⏩ 🌘 🍭 📇. & ⚫️ ⚓️ 🔛 🎏 🐍 🆎 🔑, 👨🎨 🐕🦺 👑.
+
+!!! check "**FastAPI** ⚙️ ⚫️"
+ 🍵 🌐 💽 🔬, 💽 🛠️ & 🏧 🏷 🧾 (⚓️ 🔛 🎻 🔗).
+
+ **FastAPI** ⤴️ ✊ 👈 🎻 🔗 💽 & 🚮 ⚫️ 🗄, ↖️ ⚪️➡️ 🌐 🎏 👜 ⚫️ 🔨.
+
+### 💃
+
+💃 💿 🔫 🛠️/🧰, ❔ 💯 🏗 ↕-🎭 ✳ 🐕🦺.
+
+⚫️ 📶 🙅 & 🏋️. ⚫️ 🔧 💪 🏧, & ✔️ 🔧 🦲.
+
+⚫️ ✔️:
+
+* 🤙 🎆 🎭.
+* *️⃣ 🐕🦺.
+* -🛠️ 🖥 📋.
+* 🕴 & 🤫 🎉.
+* 💯 👩💻 🏗 🔛 🇸🇲.
+* ⚜, 🗜, 🎻 📁, 🎏 📨.
+* 🎉 & 🍪 🐕🦺.
+* 1️⃣0️⃣0️⃣ 💯 💯 💰.
+* 1️⃣0️⃣0️⃣ 💯 🆎 ✍ ✍.
+* 👩❤👨 🏋️ 🔗.
+
+💃 ⏳ ⏩ 🐍 🛠️ 💯. 🕴 💥 Uvicorn, ❔ 🚫 🛠️, ✋️ 💽.
+
+💃 🚚 🌐 🔰 🕸 🕸 🛠️.
+
+✋️ ⚫️ 🚫 🚚 🏧 💽 🔬, 🛠️ ⚖️ 🧾.
+
+👈 1️⃣ 👑 👜 👈 **FastAPI** 🚮 🔛 🔝, 🌐 ⚓️ 🔛 🐍 🆎 🔑 (⚙️ Pydantic). 👈, ➕ 🔗 💉 ⚙️, 💂♂ 🚙, 🗄 🔗 ⚡, ♒️.
+
+!!! note "📡 ℹ"
+ 🔫 🆕 "🐩" ➖ 🛠️ ✳ 🐚 🏉 👨🎓. ⚫️ 🚫 "🐍 🐩" (🇩🇬), 👐 👫 🛠️ 🔨 👈.
+
+ 👐, ⚫️ ⏪ ➖ ⚙️ "🐩" 📚 🧰. 👉 📉 📉 🛠️, 👆 💪 🎛 Uvicorn 🙆 🎏 🔫 💽 (💖 👸 ⚖️ Hypercorn), ⚖️ 👆 💪 🚮 🔫 🔗 🧰, 💖 `python-socketio`.
+
+!!! check "**FastAPI** ⚙️ ⚫️"
+ 🍵 🌐 🐚 🕸 🍕. ❎ ⚒ 🔛 🔝.
+
+ 🎓 `FastAPI` ⚫️ 😖 🔗 ⚪️➡️ 🎓 `Starlette`.
+
+ , 🕳 👈 👆 💪 ⏮️ 💃, 👆 💪 ⚫️ 🔗 ⏮️ **FastAPI**, ⚫️ 🌖 💃 🔛 💊.
+
+### Uvicorn
+
+Uvicorn 🌩-⏩ 🔫 💽, 🏗 🔛 uvloop & httptool.
+
+⚫️ 🚫 🕸 🛠️, ✋️ 💽. 🖼, ⚫️ 🚫 🚚 🧰 🕹 ➡. 👈 🕳 👈 🛠️ 💖 💃 (⚖️ **FastAPI**) 🔜 🚚 🔛 🔝.
+
+⚫️ 👍 💽 💃 & **FastAPI**.
+
+!!! check "**FastAPI** 👍 ⚫️"
+ 👑 🕸 💽 🏃 **FastAPI** 🈸.
+
+ 👆 💪 🌀 ⚫️ ⏮️ 🐁, ✔️ 🔁 👁-🛠️ 💽.
+
+ ✅ 🌅 ℹ [🛠️](deployment/index.md){.internal-link target=_blank} 📄.
+
+## 📇 & 🚅
+
+🤔, 🔬, & 👀 🔺 🖖 Uvicorn, 💃 & FastAPI, ✅ 📄 🔃 [📇](benchmarks.md){.internal-link target=_blank}.
diff --git a/docs/em/docs/async.md b/docs/em/docs/async.md
new file mode 100644
index 000000000..13b362b5d
--- /dev/null
+++ b/docs/em/docs/async.md
@@ -0,0 +1,430 @@
+# 🛠️ & 🔁 / ⌛
+
+ℹ 🔃 `async def` ❕ *➡ 🛠️ 🔢* & 🖥 🔃 🔁 📟, 🛠️, & 🔁.
+
+## 🏃 ❓
+
+🆑;👩⚕️:
+
+🚥 👆 ⚙️ 🥉 🥳 🗃 👈 💬 👆 🤙 👫 ⏮️ `await`, 💖:
+
+```Python
+results = await some_library()
+```
+
+⤴️, 📣 👆 *➡ 🛠️ 🔢* ⏮️ `async def` 💖:
+
+```Python hl_lines="2"
+@app.get('/')
+async def read_results():
+ results = await some_library()
+ return results
+```
+
+!!! note
+ 👆 💪 🕴 ⚙️ `await` 🔘 🔢 ✍ ⏮️ `async def`.
+
+---
+
+🚥 👆 ⚙️ 🥉 🥳 🗃 👈 🔗 ⏮️ 🕳 (💽, 🛠️, 📁 ⚙️, ♒️.) & 🚫 ✔️ 🐕🦺 ⚙️ `await`, (👉 ⏳ 💼 🌅 💽 🗃), ⤴️ 📣 👆 *➡ 🛠️ 🔢* 🛎, ⏮️ `def`, 💖:
+
+```Python hl_lines="2"
+@app.get('/')
+def results():
+ results = some_library()
+ return results
+```
+
+---
+
+🚥 👆 🈸 (😫) 🚫 ✔️ 🔗 ⏮️ 🕳 🙆 & ⌛ ⚫️ 📨, ⚙️ `async def`.
+
+---
+
+🚥 👆 🚫 💭, ⚙️ 😐 `def`.
+
+---
+
+**🗒**: 👆 💪 🌀 `def` & `async def` 👆 *➡ 🛠️ 🔢* 🌅 👆 💪 & 🔬 🔠 1️⃣ ⚙️ 🏆 🎛 👆. FastAPI 🔜 ▶️️ 👜 ⏮️ 👫.
+
+😆, 🙆 💼 🔛, FastAPI 🔜 👷 🔁 & 📶 ⏩.
+
+✋️ 📄 📶 🔛, ⚫️ 🔜 💪 🎭 🛠️.
+
+## 📡 ℹ
+
+🏛 ⏬ 🐍 ✔️ 🐕🦺 **"🔁 📟"** ⚙️ 🕳 🤙 **"🔁"**, ⏮️ **`async` & `await`** ❕.
+
+➡️ 👀 👈 🔤 🍕 📄 🔛:
+
+* **🔁 📟**
+* **`async` & `await`**
+* **🔁**
+
+## 🔁 📟
+
+🔁 📟 ⛓ 👈 🇪🇸 👶 ✔️ 🌌 💬 💻 / 📋 👶 👈 ☝ 📟, ⚫️ 👶 🔜 ✔️ ⌛ *🕳 🙆* 🏁 👱 🙆. ➡️ 💬 👈 *🕳 🙆* 🤙 "🐌-📁" 👶.
+
+, ⏮️ 👈 🕰, 💻 💪 🚶 & 🎏 👷, ⏪ "🐌-📁" 👶 🏁.
+
+⤴️ 💻 / 📋 👶 🔜 👟 🔙 🔠 🕰 ⚫️ ✔️ 🤞 ↩️ ⚫️ ⌛ 🔄, ⚖️ 🕐❔ ⚫️ 👶 🏁 🌐 👷 ⚫️ ✔️ 👈 ☝. & ⚫️ 👶 🔜 👀 🚥 🙆 📋 ⚫️ ⌛ ✔️ ⏪ 🏁, 🤸 ⚫️❔ ⚫️ ✔️.
+
+⏭, ⚫️ 👶 ✊ 🥇 📋 🏁 (➡️ 💬, 👆 "🐌-📁" 👶) & 😣 ⚫️❔ ⚫️ ✔️ ⏮️ ⚫️.
+
+👈 "⌛ 🕳 🙆" 🛎 🔗 👤/🅾 🛠️ 👈 📶 "🐌" (🔬 🚅 🕹 & 💾 💾), 💖 ⌛:
+
+* 📊 ⚪️➡️ 👩💻 📨 🔘 🕸
+* 📊 📨 👆 📋 📨 👩💻 🔘 🕸
+* 🎚 📁 💾 ✍ ⚙️ & 🤝 👆 📋
+* 🎚 👆 📋 🤝 ⚙️ ✍ 💾
+* 🛰 🛠️ 🛠️
+* 💽 🛠️ 🏁
+* 💽 🔢 📨 🏁
+* ♒️.
+
+🛠️ 🕰 🍴 ✴️ ⌛ 👤/🅾 🛠️, 👫 🤙 👫 "👤/🅾 🔗" 🛠️.
+
+⚫️ 🤙 "🔁" ↩️ 💻 / 📋 🚫 ✔️ "🔁" ⏮️ 🐌 📋, ⌛ ☑ 🙍 👈 📋 🏁, ⏪ 🔨 🕳, 💪 ✊ 📋 🏁 & 😣 👷.
+
+↩️ 👈, 💆♂ "🔁" ⚙️, 🕐 🏁, 📋 💪 ⌛ ⏸ 🐥 👄 (⏲) 💻 / 📋 🏁 ⚫️❔ ⚫️ 🚶, & ⤴️ 👟 🔙 ✊ 🏁 & 😣 👷 ⏮️ 👫.
+
+"🔁" (👽 "🔁") 👫 🛎 ⚙️ ⚖ "🔁", ↩️ 💻 / 📋 ⏩ 🌐 📶 🔁 ⏭ 🔀 🎏 📋, 🚥 👈 🔁 🔌 ⌛.
+
+### 🛠️ & 🍔
+
+👉 💭 **🔁** 📟 🔬 🔛 🕣 🤙 **"🛠️"**. ⚫️ 🎏 ⚪️➡️ **"🔁"**.
+
+**🛠️** & **🔁** 👯♂️ 🔗 "🎏 👜 😥 🌅 ⚖️ 🌘 🎏 🕰".
+
+✋️ ℹ 🖖 *🛠️* & *🔁* 🎏.
+
+👀 🔺, 🌈 📄 📖 🔃 🍔:
+
+### 🛠️ 🍔
+
+👆 🚶 ⏮️ 👆 🥰 🤚 ⏩ 🥕, 👆 🧍 ⏸ ⏪ 🏧 ✊ ✔ ⚪️➡️ 👫👫 🚪 👆. 👶
+
+
+
+⤴️ ⚫️ 👆 🔄, 👆 🥉 👆 ✔ 2️⃣ 📶 🎀 🍔 👆 🥰 & 👆. 👶 👶
+
+
+
+🏧 💬 🕳 🍳 👨🍳 👫 💭 👫 ✔️ 🏗 👆 🍔 (✋️ 👫 ⏳ 🏗 🕐 ⏮️ 👩💻).
+
+
+
+👆 💸. 👶
+
+🏧 🤝 👆 🔢 👆 🔄.
+
+
+
+⏪ 👆 ⌛, 👆 🚶 ⏮️ 👆 🥰 & ⚒ 🏓, 👆 🧎 & 💬 ⏮️ 👆 🥰 📏 🕰 (👆 🍔 📶 🎀 & ✊ 🕰 🏗).
+
+👆 🏖 🏓 ⏮️ 👆 🥰, ⏪ 👆 ⌛ 🍔, 👆 💪 💸 👈 🕰 😮 ❔ 👌, 🐨 & 🙃 👆 🥰 👶 👶 👶.
+
+
+
+⏪ ⌛ & 💬 👆 🥰, ⚪️➡️ 🕰 🕰, 👆 ✅ 🔢 🖥 🔛 ⏲ 👀 🚥 ⚫️ 👆 🔄 ⏪.
+
+⤴️ ☝, ⚫️ 😒 👆 🔄. 👆 🚶 ⏲, 🤚 👆 🍔 & 👟 🔙 🏓.
+
+
+
+👆 & 👆 🥰 🍴 🍔 & ✔️ 👌 🕰. 👶
+
+
+
+!!! info
+ 🌹 🖼 👯 🍏. 👶
+
+---
+
+🌈 👆 💻 / 📋 👶 👈 📖.
+
+⏪ 👆 ⏸, 👆 ⛽ 👶, ⌛ 👆 🔄, 🚫 🔨 🕳 📶 "😌". ✋️ ⏸ ⏩ ↩️ 🏧 🕴 ✊ ✔ (🚫 🏗 👫), 👈 👌.
+
+⤴️, 🕐❔ ⚫️ 👆 🔄, 👆 ☑ "😌" 👷, 👆 🛠️ 🍣, 💭 ⚫️❔ 👆 💚, 🤚 👆 🥰 ⚒, 💸, ✅ 👈 👆 🤝 ☑ 💵 ⚖️ 💳, ✅ 👈 👆 🈚 ☑, ✅ 👈 ✔ ✔️ ☑ 🏬, ♒️.
+
+✋️ ⤴️, ✋️ 👆 🚫 ✔️ 👆 🍔, 👆 👷 ⏮️ 🏧 "🔛 ⏸" ⏸, ↩️ 👆 ✔️ ⌛ 👶 👆 🍔 🔜.
+
+✋️ 👆 🚶 ↖️ ⚪️➡️ ⏲ & 🧎 🏓 ⏮️ 🔢 👆 🔄, 👆 💪 🎛 👶 👆 🙋 👆 🥰, & "👷" 👶 👶 🔛 👈. ⤴️ 👆 🔄 🔨 🕳 📶 "😌" 😏 ⏮️ 👆 🥰 👶.
+
+⤴️ 🏧 👶 💬 "👤 🏁 ⏮️ 🔨 🍔" 🚮 👆 🔢 🔛 ⏲ 🖥, ✋️ 👆 🚫 🦘 💖 😜 ⏪ 🕐❔ 🖥 🔢 🔀 👆 🔄 🔢. 👆 💭 🙅♂ 1️⃣ 🔜 📎 👆 🍔 ↩️ 👆 ✔️ 🔢 👆 🔄, & 👫 ✔️ 👫.
+
+👆 ⌛ 👆 🥰 🏁 📖 (🏁 ⏮️ 👷 👶 / 📋 ➖ 🛠️ 👶), 😀 🖐 & 💬 👈 👆 🔜 🍔 ⏸.
+
+⤴️ 👆 🚶 ⏲ 👶, ▶️ 📋 👈 🔜 🏁 👶, ⚒ 🍔, 💬 👏 & ✊ 👫 🏓. 👈 🏁 👈 🔁 / 📋 🔗 ⏮️ ⏲ ⏹. 👈 🔄, ✍ 🆕 📋, "🍴 🍔" 👶 👶, ✋️ ⏮️ 1️⃣ "🤚 🍔" 🏁 ⏹.
+
+### 🔗 🍔
+
+🔜 ➡️ 🌈 👫 ➖🚫 🚫 "🛠️ 🍔", ✋️ "🔗 🍔".
+
+👆 🚶 ⏮️ 👆 🥰 🤚 🔗 ⏩ 🥕.
+
+👆 🧍 ⏸ ⏪ 📚 (➡️ 💬 8️⃣) 🏧 👈 🎏 🕰 🍳 ✊ ✔ ⚪️➡️ 👫👫 🚪 👆.
+
+👱 ⏭ 👆 ⌛ 👫 🍔 🔜 ⏭ 🍂 ⏲ ↩️ 🔠 8️⃣ 🏧 🚶 & 🏗 🍔 ▶️️ ↖️ ⏭ 💆♂ ⏭ ✔.
+
+
+
+⤴️ ⚫️ 😒 👆 🔄, 👆 🥉 👆 ✔ 2️⃣ 📶 🎀 🍔 👆 🥰 & 👆.
+
+👆 💸 👶.
+
+
+
+🏧 🚶 👨🍳.
+
+👆 ⌛, 🧍 🚪 ⏲ 👶, 👈 🙅♂ 1️⃣ 🙆 ✊ 👆 🍔 ⏭ 👆, 📤 🙅♂ 🔢 🔄.
+
+
+
+👆 & 👆 🥰 😩 🚫 ➡️ 🙆 🤚 🚪 👆 & ✊ 👆 🍔 🕐❔ 👫 🛬, 👆 🚫🔜 💸 🙋 👆 🥰. 👶
+
+👉 "🔁" 👷, 👆 "🔁" ⏮️ 🏧/🍳 👶 👶. 👆 ✔️ ⌛ 👶 & 📤 ☑ 🙍 👈 🏧/🍳 👶 👶 🏁 🍔 & 🤝 👫 👆, ⚖️ ⏪, 👱 🙆 💪 ✊ 👫.
+
+
+
+⤴️ 👆 🏧/🍳 👶 👶 😒 👟 🔙 ⏮️ 👆 🍔, ⏮️ 📏 🕰 ⌛ 👶 📤 🚪 ⏲.
+
+
+
+👆 ✊ 👆 🍔 & 🚶 🏓 ⏮️ 👆 🥰.
+
+👆 🍴 👫, & 👆 🔨. ⏹
+
+
+
+📤 🚫 🌅 💬 ⚖️ 😏 🌅 🕰 💸 ⌛ 👶 🚪 ⏲. 👶
+
+!!! info
+ 🌹 🖼 👯 🍏. 👶
+
+---
+
+👉 😐 🔗 🍔, 👆 💻 / 📋 👶 ⏮️ 2️⃣ 🕹 (👆 & 👆 🥰), 👯♂️ ⌛ 👶 & 💡 👫 🙋 👶 "⌛ 🔛 ⏲" 👶 📏 🕰.
+
+⏩ 🥕 🏪 ✔️ 8️⃣ 🕹 (🏧/🍳). ⏪ 🛠️ 🍔 🏪 💪 ✔️ ✔️ 🕴 2️⃣ (1️⃣ 🏧 & 1️⃣ 🍳).
+
+✋️, 🏁 💡 🚫 🏆. 👶
+
+---
+
+👉 🔜 🔗 🌓 📖 🍔. 👶
+
+🌅 "🎰 👨❤👨" 🖼 👉, 🌈 🏦.
+
+🆙 ⏳, 🏆 🏦 ✔️ 💗 🏧 👶 👶 👶 👶 👶 👶 👶 👶 & 🦏 ⏸ 👶 👶 👶 👶 👶 👶 👶 👶.
+
+🌐 🏧 🔨 🌐 👷 ⏮️ 1️⃣ 👩💻 ⏮️ 🎏 👶 👶 👶.
+
+& 👆 ✔️ ⌛ 👶 ⏸ 📏 🕰 ⚖️ 👆 💸 👆 🔄.
+
+👆 🎲 🚫🔜 💚 ✊ 👆 🥰 👶 ⏮️ 👆 👷 🏦 👶.
+
+### 🍔 🏁
+
+👉 😐 "⏩ 🥕 🍔 ⏮️ 👆 🥰", 📤 📚 ⌛ 👶, ⚫️ ⚒ 📚 🌅 🔑 ✔️ 🛠️ ⚙️ ⏸ 👶 👶.
+
+👉 💼 🌅 🕸 🈸.
+
+📚, 📚 👩💻, ✋️ 👆 💽 ⌛ 👶 👫 🚫--👍 🔗 📨 👫 📨.
+
+& ⤴️ ⌛ 👶 🔄 📨 👟 🔙.
+
+👉 "⌛" 👶 ⚖ ⏲, ✋️, ⚖ ⚫️ 🌐, ⚫️ 📚 ⌛ 🔚.
+
+👈 ⚫️❔ ⚫️ ⚒ 📚 🔑 ⚙️ 🔁 ⏸ 👶 👶 📟 🕸 🔗.
+
+👉 😇 🔀 ⚫️❔ ⚒ ✳ 🌟 (✋️ ✳ 🚫 🔗) & 👈 💪 🚶 🛠️ 🇪🇸.
+
+& 👈 🎏 🎚 🎭 👆 🤚 ⏮️ **FastAPI**.
+
+& 👆 💪 ✔️ 🔁 & 🔀 🎏 🕰, 👆 🤚 ↕ 🎭 🌘 🌅 💯 ✳ 🛠️ & 🔛 🇷🇪 ⏮️ 🚶, ❔ ✍ 🇪🇸 🔐 🅱 (🌐 👏 💃).
+
+### 🛠️ 👍 🌘 🔁 ❓
+
+😆 ❗ 👈 🚫 🛐 📖.
+
+🛠️ 🎏 🌘 🔁. & ⚫️ 👻 🔛 **🎯** 😐 👈 🔌 📚 ⌛. ↩️ 👈, ⚫️ 🛎 📚 👍 🌘 🔁 🕸 🈸 🛠️. ✋️ 🚫 🌐.
+
+, ⚖ 👈 👅, 🌈 📄 📏 📖:
+
+> 👆 ✔️ 🧹 🦏, 💩 🏠.
+
+*😆, 👈 🎂 📖*.
+
+---
+
+📤 🙅♂ ⌛ 👶 🙆, 📚 👷 🔨, 🔛 💗 🥉 🏠.
+
+👆 💪 ✔️ 🔄 🍔 🖼, 🥇 🏠 🧖♂, ⤴️ 👨🍳, ✋️ 👆 🚫 ⌛ 👶 🕳, 🧹 & 🧹, 🔄 🚫🔜 📉 🕳.
+
+⚫️ 🔜 ✊ 🎏 💸 🕰 🏁 ⏮️ ⚖️ 🍵 🔄 (🛠️) & 👆 🔜 ✔️ ⌛ 🎏 💸 👷.
+
+✋️ 👉 💼, 🚥 👆 💪 ✊️ 8️⃣ 👰-🏧/🍳/🔜-🧹, & 🔠 1️⃣ 👫 (➕ 👆) 💪 ✊ 🏒 🏠 🧹 ⚫️, 👆 💪 🌐 👷 **🔗**, ⏮️ ➕ ℹ, & 🏁 🌅 🔜.
+
+👉 😐, 🔠 1️⃣ 🧹 (🔌 👆) 🔜 🕹, 🤸 👫 🍕 👨🏭.
+
+& 🏆 🛠️ 🕰 ✊ ☑ 👷 (↩️ ⌛), & 👷 💻 ⌛ 💽, 👫 🤙 👫 ⚠ "💽 🎁".
+
+---
+
+⚠ 🖼 💽 🔗 🛠️ 👜 👈 🚚 🏗 🧪 🏭.
+
+🖼:
+
+* **🎧** ⚖️ **🖼 🏭**.
+* **💻 👓**: 🖼 ✍ 💯 🔅, 🔠 🔅 ✔️ 3️⃣ 💲 / 🎨, 🏭 👈 🛎 🚚 💻 🕳 🔛 📚 🔅, 🌐 🎏 🕰.
+* **🎰 🏫**: ⚫️ 🛎 🚚 📚 "✖" & "🖼" ✖. 💭 🦏 📋 ⏮️ 🔢 & ✖ 🌐 👫 👯♂️ 🎏 🕰.
+* **⏬ 🏫**: 👉 🎧-🏑 🎰 🏫,, 🎏 ✔. ⚫️ 👈 📤 🚫 👁 📋 🔢 ✖, ✋️ 🦏 ⚒ 👫, & 📚 💼, 👆 ⚙️ 🎁 🕹 🏗 & / ⚖️ ⚙️ 👈 🏷.
+
+### 🛠️ ➕ 🔁: 🕸 ➕ 🎰 🏫
+
+⏮️ **FastAPI** 👆 💪 ✊ 📈 🛠️ 👈 📶 ⚠ 🕸 🛠️ (🎏 👑 🧲 ✳).
+
+✋️ 👆 💪 🐄 💰 🔁 & 💾 (✔️ 💗 🛠️ 🏃♂ 🔗) **💽 🎁** ⚖ 💖 👈 🎰 🏫 ⚙️.
+
+👈, ➕ 🙅 👐 👈 🐍 👑 🇪🇸 **💽 🧪**, 🎰 🏫 & ✴️ ⏬ 🏫, ⚒ FastAPI 📶 👍 🏏 💽 🧪 / 🎰 🏫 🕸 🔗 & 🈸 (👪 📚 🎏).
+
+👀 ❔ 🏆 👉 🔁 🏭 👀 📄 🔃 [🛠️](deployment/index.md){.internal-link target=_blank}.
+
+## `async` & `await`
+
+🏛 ⏬ 🐍 ✔️ 📶 🏋️ 🌌 🔬 🔁 📟. 👉 ⚒ ⚫️ 👀 💖 😐 "🔁" 📟 & "⌛" 👆 ▶️️ 🙍.
+
+🕐❔ 📤 🛠️ 👈 🔜 🚚 ⌛ ⏭ 🤝 🏁 & ✔️ 🐕🦺 👉 🆕 🐍 ⚒, 👆 💪 📟 ⚫️ 💖:
+
+```Python
+burgers = await get_burgers(2)
+```
+
+🔑 📥 `await`. ⚫️ 💬 🐍 👈 ⚫️ ✔️ ⌛ ⏸ `get_burgers(2)` 🏁 🔨 🚮 👜 👶 ⏭ ♻ 🏁 `burgers`. ⏮️ 👈, 🐍 🔜 💭 👈 ⚫️ 💪 🚶 & 🕳 🙆 👶 👶 👐 (💖 📨 ➕1️⃣ 📨).
+
+`await` 👷, ⚫️ ✔️ 🔘 🔢 👈 🐕🦺 👉 🔀. 👈, 👆 📣 ⚫️ ⏮️ `async def`:
+
+```Python hl_lines="1"
+async def get_burgers(number: int):
+ # Do some asynchronous stuff to create the burgers
+ return burgers
+```
+
+...↩️ `def`:
+
+```Python hl_lines="2"
+# This is not asynchronous
+def get_sequential_burgers(number: int):
+ # Do some sequential stuff to create the burgers
+ return burgers
+```
+
+⏮️ `async def`, 🐍 💭 👈, 🔘 👈 🔢, ⚫️ ✔️ 🤔 `await` 🧬, & 👈 ⚫️ 💪 "⏸" ⏸ 🛠️ 👈 🔢 & 🚶 🕳 🙆 👶 ⏭ 👟 🔙.
+
+🕐❔ 👆 💚 🤙 `async def` 🔢, 👆 ✔️ "⌛" ⚫️. , 👉 🏆 🚫 👷:
+
+```Python
+# This won't work, because get_burgers was defined with: async def
+burgers = get_burgers(2)
+```
+
+---
+
+, 🚥 👆 ⚙️ 🗃 👈 💬 👆 👈 👆 💪 🤙 ⚫️ ⏮️ `await`, 👆 💪 ✍ *➡ 🛠️ 🔢* 👈 ⚙️ ⚫️ ⏮️ `async def`, 💖:
+
+```Python hl_lines="2-3"
+@app.get('/burgers')
+async def read_burgers():
+ burgers = await get_burgers(2)
+ return burgers
+```
+
+### 🌅 📡 ℹ
+
+👆 💪 ✔️ 👀 👈 `await` 💪 🕴 ⚙️ 🔘 🔢 🔬 ⏮️ `async def`.
+
+✋️ 🎏 🕰, 🔢 🔬 ⏮️ `async def` ✔️ "⌛". , 🔢 ⏮️ `async def` 💪 🕴 🤙 🔘 🔢 🔬 ⏮️ `async def` 💁♂️.
+
+, 🔃 🥚 & 🐔, ❔ 👆 🤙 🥇 `async` 🔢 ❓
+
+🚥 👆 👷 ⏮️ **FastAPI** 👆 🚫 ✔️ 😟 🔃 👈, ↩️ 👈 "🥇" 🔢 🔜 👆 *➡ 🛠️ 🔢*, & FastAPI 🔜 💭 ❔ ▶️️ 👜.
+
+✋️ 🚥 👆 💚 ⚙️ `async` / `await` 🍵 FastAPI, 👆 💪 ⚫️ 👍.
+
+### ✍ 👆 👍 🔁 📟
+
+💃 (& **FastAPI**) ⚓️ 🔛 AnyIO, ❔ ⚒ ⚫️ 🔗 ⏮️ 👯♂️ 🐍 🐩 🗃 ✳ & 🎻.
+
+🎯, 👆 💪 🔗 ⚙️ AnyIO 👆 🏧 🛠️ ⚙️ 💼 👈 🚚 🌅 🏧 ⚓ 👆 👍 📟.
+
+& 🚥 👆 🚫 ⚙️ FastAPI, 👆 💪 ✍ 👆 👍 🔁 🈸 ⏮️ AnyIO 🏆 🔗 & 🤚 🚮 💰 (✅ *📊 🛠️*).
+
+### 🎏 📨 🔁 📟
+
+👉 👗 ⚙️ `async` & `await` 📶 🆕 🇪🇸.
+
+✋️ ⚫️ ⚒ 👷 ⏮️ 🔁 📟 📚 ⏩.
+
+👉 🎏 ❕ (⚖️ 🌖 🌓) 🔌 ⏳ 🏛 ⏬ 🕸 (🖥 & ✳).
+
+✋️ ⏭ 👈, 🚚 🔁 📟 🌖 🏗 & ⚠.
+
+⏮️ ⏬ 🐍, 👆 💪 ✔️ ⚙️ 🧵 ⚖️ 🐁. ✋️ 📟 🌌 🌖 🏗 🤔, ℹ, & 💭 🔃.
+
+⏮️ ⏬ ✳ / 🖥 🕸, 👆 🔜 ✔️ ⚙️ "⏲". ❔ ↘️ ⏲ 🔥😈.
+
+## 🔁
+
+**🔁** 📶 🎀 ⚖ 👜 📨 `async def` 🔢. 🐍 💭 👈 ⚫️ 🕳 💖 🔢 👈 ⚫️ 💪 ▶️ & 👈 ⚫️ 🔜 🔚 ☝, ✋️ 👈 ⚫️ 5️⃣📆 ⏸ ⏸ 🔘 💁♂️, 🕐❔ 📤 `await` 🔘 ⚫️.
+
+✋️ 🌐 👉 🛠️ ⚙️ 🔁 📟 ⏮️ `async` & `await` 📚 🕰 🔬 ⚙️ "🔁". ⚫️ ⭐ 👑 🔑 ⚒ 🚶, "🔁".
+
+## 🏁
+
+➡️ 👀 🎏 🔤 ⚪️➡️ 🔛:
+
+> 🏛 ⏬ 🐍 ✔️ 🐕🦺 **"🔁 📟"** ⚙️ 🕳 🤙 **"🔁"**, ⏮️ **`async` & `await`** ❕.
+
+👈 🔜 ⚒ 🌅 🔑 🔜. 👶
+
+🌐 👈 ⚫️❔ 🏋️ FastAPI (🔘 💃) & ⚫️❔ ⚒ ⚫️ ✔️ ✅ 🎆 🎭.
+
+## 📶 📡 ℹ
+
+!!! warning
+ 👆 💪 🎲 🚶 👉.
+
+ 👉 📶 📡 ℹ ❔ **FastAPI** 👷 🔘.
+
+ 🚥 👆 ✔️ 📡 💡 (🈶-🏋, 🧵, 🍫, ♒️.) & 😟 🔃 ❔ FastAPI 🍵 `async def` 🆚 😐 `def`, 🚶 ⤴️.
+
+### ➡ 🛠️ 🔢
+
+🕐❔ 👆 📣 *➡ 🛠️ 🔢* ⏮️ 😐 `def` ↩️ `async def`, ⚫️ 🏃 🔢 🧵 👈 ⤴️ ⌛, ↩️ ➖ 🤙 🔗 (⚫️ 🔜 🍫 💽).
+
+🚥 👆 👟 ⚪️➡️ ➕1️⃣ 🔁 🛠️ 👈 🔨 🚫 👷 🌌 🔬 🔛 & 👆 ⚙️ ⚖ 🙃 📊-🕴 *➡ 🛠️ 🔢* ⏮️ ✅ `def` 🤪 🎭 📈 (🔃 1️⃣0️⃣0️⃣ 💓), 🙏 🗒 👈 **FastAPI** ⭐ 🔜 🔄. 👫 💼, ⚫️ 👻 ⚙️ `async def` 🚥 👆 *➡ 🛠️ 🔢* ⚙️ 📟 👈 🎭 🚧 👤/🅾.
+
+, 👯♂️ ⚠, 🤞 👈 **FastAPI** 🔜 [⏩](/#performance){.internal-link target=_blank} 🌘 (⚖️ 🌘 ⭐) 👆 ⏮️ 🛠️.
+
+### 🔗
+
+🎏 ✔ [🔗](/tutorial/dependencies/index.md){.internal-link target=_blank}. 🚥 🔗 🐩 `def` 🔢 ↩️ `async def`, ⚫️ 🏃 🔢 🧵.
+
+### 🎧-🔗
+
+👆 💪 ✔️ 💗 🔗 & [🎧-🔗](/tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} 🚫 🔠 🎏 (🔢 🔢 🔑), 👫 💪 ✍ ⏮️ `async def` & ⏮️ 😐 `def`. ⚫️ 🔜 👷, & 🕐 ✍ ⏮️ 😐 `def` 🔜 🤙 🔛 🔢 🧵 (⚪️➡️ 🧵) ↩️ ➖ "⌛".
+
+### 🎏 🚙 🔢
+
+🙆 🎏 🚙 🔢 👈 👆 🤙 🔗 💪 ✍ ⏮️ 😐 `def` ⚖️ `async def` & FastAPI 🏆 🚫 📉 🌌 👆 🤙 ⚫️.
+
+👉 🔅 🔢 👈 FastAPI 🤙 👆: *➡ 🛠️ 🔢* & 🔗.
+
+🚥 👆 🚙 🔢 😐 🔢 ⏮️ `def`, ⚫️ 🔜 🤙 🔗 (👆 ✍ ⚫️ 👆 📟), 🚫 🧵, 🚥 🔢 ✍ ⏮️ `async def` ⤴️ 👆 🔜 `await` 👈 🔢 🕐❔ 👆 🤙 ⚫️ 👆 📟.
+
+---
+
+🔄, 👉 📶 📡 ℹ 👈 🔜 🎲 ⚠ 🚥 👆 👟 🔎 👫.
+
+⏪, 👆 🔜 👍 ⏮️ 📄 ⚪️➡️ 📄 🔛: 🏃 ❓.
diff --git a/docs/em/docs/benchmarks.md b/docs/em/docs/benchmarks.md
new file mode 100644
index 000000000..003c3f62d
--- /dev/null
+++ b/docs/em/docs/benchmarks.md
@@ -0,0 +1,34 @@
+# 📇
+
+🔬 🇸🇲 📇 🎦 **FastAPI** 🈸 🏃♂ 🔽 Uvicorn 1️⃣ ⏩ 🐍 🛠️ 💪, 🕴 🔛 💃 & Uvicorn 👫 (⚙️ 🔘 FastAPI). (*)
+
+✋️ 🕐❔ ✅ 📇 & 🔺 👆 🔜 ✔️ 📄 🤯.
+
+## 📇 & 🚅
+
+🕐❔ 👆 ✅ 📇, ⚫️ ⚠ 👀 📚 🧰 🎏 🆎 🔬 🌓.
+
+🎯, 👀 Uvicorn, 💃 & FastAPI 🔬 👯♂️ (👪 📚 🎏 🧰).
+
+🙅 ⚠ ❎ 🧰, 👍 🎭 ⚫️ 🔜 🤚. & 🏆 📇 🚫 💯 🌖 ⚒ 🚚 🧰.
+
+🔗 💖:
+
+* **Uvicorn**: 🔫 💽
+ * **💃**: (⚙️ Uvicorn) 🕸 🕸
+ * **FastAPI**: (⚙️ 💃) 🛠️ 🕸 ⏮️ 📚 🌖 ⚒ 🏗 🔗, ⏮️ 💽 🔬, ♒️.
+
+* **Uvicorn**:
+ * 🔜 ✔️ 🏆 🎭, ⚫️ 🚫 ✔️ 🌅 ➕ 📟 ↖️ ⚪️➡️ 💽 ⚫️.
+ * 👆 🚫🔜 ✍ 🈸 Uvicorn 🔗. 👈 🔜 ⛓ 👈 👆 📟 🔜 ✔️ 🔌 🌖 ⚖️ 🌘, 🌘, 🌐 📟 🚚 💃 (⚖️ **FastAPI**). & 🚥 👆 👈, 👆 🏁 🈸 🔜 ✔️ 🎏 🌥 ✔️ ⚙️ 🛠️ & 📉 👆 📱 📟 & 🐛.
+ * 🚥 👆 ⚖ Uvicorn, 🔬 ⚫️ 🛡 👸, Hypercorn, ✳, ♒️. 🈸 💽.
+* **💃**:
+ * 🔜 ✔️ ⏭ 🏆 🎭, ⏮️ Uvicorn. 👐, 💃 ⚙️ Uvicorn 🏃. , ⚫️ 🎲 💪 🕴 🤚 "🐌" 🌘 Uvicorn ✔️ 🛠️ 🌅 📟.
+ * ✋️ ⚫️ 🚚 👆 🧰 🏗 🙅 🕸 🈸, ⏮️ 🕹 ⚓️ 🔛 ➡, ♒️.
+ * 🚥 👆 ⚖ 💃, 🔬 ⚫️ 🛡 🤣, 🏺, ✳, ♒️. 🕸 🛠️ (⚖️ 🕸).
+* **FastAPI**:
+ * 🎏 🌌 👈 💃 ⚙️ Uvicorn & 🚫🔜 ⏩ 🌘 ⚫️, **FastAPI** ⚙️ 💃, ⚫️ 🚫🔜 ⏩ 🌘 ⚫️.
+ * FastAPI 🚚 🌅 ⚒ 🔛 🔝 💃. ⚒ 👈 👆 🌖 🕧 💪 🕐❔ 🏗 🔗, 💖 💽 🔬 & 🛠️. & ⚙️ ⚫️, 👆 🤚 🏧 🧾 🆓 (🏧 🧾 🚫 🚮 🌥 🏃♂ 🈸, ⚫️ 🏗 🔛 🕴).
+ * 🚥 👆 🚫 ⚙️ FastAPI & ⚙️ 💃 🔗 (⚖️ ➕1️⃣ 🧰, 💖 🤣, 🏺, 🆘, ♒️) 👆 🔜 ✔️ 🛠️ 🌐 💽 🔬 & 🛠️ 👆. , 👆 🏁 🈸 🔜 ✔️ 🎏 🌥 🚥 ⚫️ 🏗 ⚙️ FastAPI. & 📚 💼, 👉 💽 🔬 & 🛠️ 🦏 💸 📟 ✍ 🈸.
+ * , ⚙️ FastAPI 👆 ♻ 🛠️ 🕰, 🐛, ⏸ 📟, & 👆 🔜 🎲 🤚 🎏 🎭 (⚖️ 👍) 👆 🔜 🚥 👆 🚫 ⚙️ ⚫️ (👆 🔜 ✔️ 🛠️ ⚫️ 🌐 👆 📟).
+ * 🚥 👆 ⚖ FastAPI, 🔬 ⚫️ 🛡 🕸 🈸 🛠️ (⚖️ ⚒ 🧰) 👈 🚚 💽 🔬, 🛠️ & 🧾, 💖 🏺-apispec, NestJS, ♨, ♒️. 🛠️ ⏮️ 🛠️ 🏧 💽 🔬, 🛠️ & 🧾.
diff --git a/docs/em/docs/contributing.md b/docs/em/docs/contributing.md
new file mode 100644
index 000000000..7749d27a1
--- /dev/null
+++ b/docs/em/docs/contributing.md
@@ -0,0 +1,465 @@
+# 🛠️ - 📉
+
+🥇, 👆 💪 💚 👀 🔰 🌌 [ℹ FastAPI & 🤚 ℹ](help-fastapi.md){.internal-link target=_blank}.
+
+## 🛠️
+
+🚥 👆 ⏪ 🖖 🗃 & 👆 💭 👈 👆 💪 ⏬ 🤿 📟, 📥 📄 ⚒ 🆙 👆 🌐.
+
+### 🕹 🌐 ⏮️ `venv`
+
+👆 💪 ✍ 🕹 🌐 📁 ⚙️ 🐍 `venv` 🕹:
+
+
+
+---
+
+🔜 👈 👥 💭 🔺 🖖 ⚖ **🛠️** & **📋**, ➡️ 😣 💬 🔃 🛠️.
+
+## 🏃♂ 🔛 🕴
+
+🌅 💼, 🕐❔ 👆 ✍ 🕸 🛠️, 👆 💚 ⚫️ **🕧 🏃♂**, ➡, 👈 👆 👩💻 💪 🕧 🔐 ⚫️. 👉 ↗️, 🚥 👆 ✔️ 🎯 🤔 ⚫️❔ 👆 💚 ⚫️ 🏃 🕴 🎯 ⚠, ✋️ 🌅 🕰 👆 💚 ⚫️ 🕧 🏃♂ & **💪**.
+
+### 🛰 💽
+
+🕐❔ 👆 ⚒ 🆙 🛰 💽 (☁ 💽, 🕹 🎰, ♒️.) 🙅 👜 👆 💪 🏃 Uvicorn (⚖️ 🎏) ❎, 🎏 🌌 👆 🕐❔ 🛠️ 🌐.
+
+& ⚫️ 🔜 👷 & 🔜 ⚠ **⏮️ 🛠️**.
+
+✋️ 🚥 👆 🔗 💽 💸, **🏃♂ 🛠️** 🔜 🎲 ☠️.
+
+& 🚥 💽 ⏏ (🖼 ⏮️ ℹ, ⚖️ 🛠️ ⚪️➡️ ☁ 🐕🦺) 👆 🎲 **🏆 🚫 👀 ⚫️**. & ↩️ 👈, 👆 🏆 🚫 💭 👈 👆 ✔️ ⏏ 🛠️ ❎. , 👆 🛠️ 🔜 🚧 ☠️. 👶
+
+### 🏃 🔁 🔛 🕴
+
+🏢, 👆 🔜 🎲 💚 💽 📋 (✅ Uvicorn) ▶️ 🔁 🔛 💽 🕴, & 🍵 💪 🙆 **🗿 🏥**, ✔️ 🛠️ 🕧 🏃 ⏮️ 👆 🛠️ (✅ Uvicorn 🏃♂ 👆 FastAPI 📱).
+
+### 🎏 📋
+
+🏆 👉, 👆 🔜 🛎 ✔️ **🎏 📋** 👈 🔜 ⚒ 💭 👆 🈸 🏃 🔛 🕴. & 📚 💼, ⚫️ 🔜 ⚒ 💭 🎏 🦲 ⚖️ 🈸 🏃, 🖼, 💽.
+
+### 🖼 🧰 🏃 🕴
+
+🖼 🧰 👈 💪 👉 👨🏭:
+
+* ☁
+* Kubernete
+* ☁ ✍
+* ☁ 🐝 📳
+* ✳
+* 👨💻
+* 🍵 🔘 ☁ 🐕🦺 🍕 👫 🐕🦺
+* 🎏...
+
+👤 🔜 🤝 👆 🌅 🧱 🖼 ⏭ 📃.
+
+## ⏏
+
+🎏 ⚒ 💭 👆 🈸 🏃 🔛 🕴, 👆 🎲 💚 ⚒ 💭 ⚫️ **⏏** ⏮️ ❌.
+
+### 👥 ⚒ ❌
+
+👥, 🗿, ⚒ **❌**, 🌐 🕰. 🖥 🌖 *🕧* ✔️ **🐛** 🕵♂ 🎏 🥉. 👶
+
+& 👥 👩💻 🚧 📉 📟 👥 🔎 👈 🐛 & 👥 🛠️ 🆕 ⚒ (🎲 ❎ 🆕 🐛 💁♂️ 👶).
+
+### 🤪 ❌ 🔁 🍵
+
+🕐❔ 🏗 🕸 🔗 ⏮️ FastAPI, 🚥 📤 ❌ 👆 📟, FastAPI 🔜 🛎 🔌 ⚫️ 👁 📨 👈 ⏲ ❌. 🛡
+
+👩💻 🔜 🤚 **5️⃣0️⃣0️⃣ 🔗 💽 ❌** 👈 📨, ✋️ 🈸 🔜 😣 👷 ⏭ 📨 ↩️ 💥 🍕.
+
+### 🦏 ❌ - 💥
+
+👐, 📤 5️⃣📆 💼 🌐❔ 👥 ✍ 📟 👈 **💥 🎂 🈸** ⚒ Uvicorn & 🐍 💥. 👶
+
+& , 👆 🔜 🎲 🚫 💚 🈸 🚧 ☠️ ↩️ 📤 ❌ 1️⃣ 🥉, 👆 🎲 💚 ⚫️ **😣 🏃** 🌘 *➡ 🛠️* 👈 🚫 💔.
+
+### ⏏ ⏮️ 💥
+
+✋️ 👈 💼 ⏮️ 🤙 👎 ❌ 👈 💥 🏃♂ **🛠️**, 👆 🔜 💚 🔢 🦲 👈 🈚 **🔁** 🛠️, 🌘 👩❤👨 🕰...
+
+!!! tip
+ ...👐 🚥 🎂 🈸 **💥 ⏪** ⚫️ 🎲 🚫 ⚒ 🔑 🚧 🔁 ⚫️ ♾. ✋️ 📚 💼, 👆 🔜 🎲 👀 ⚫️ ⏮️ 🛠️, ⚖️ 🌘 ▶️️ ⏮️ 🛠️.
+
+ ➡️ 🎯 🔛 👑 💼, 🌐❔ ⚫️ 💪 💥 🍕 🎯 💼 **🔮**, & ⚫️ ⚒ 🔑 ⏏ ⚫️.
+
+👆 🔜 🎲 💚 ✔️ 👜 🈚 🔁 👆 🈸 **🔢 🦲**, ↩️ 👈 ☝, 🎏 🈸 ⏮️ Uvicorn & 🐍 ⏪ 💥, 📤 🕳 🎏 📟 🎏 📱 👈 💪 🕳 🔃 ⚫️.
+
+### 🖼 🧰 ⏏ 🔁
+
+🏆 💼, 🎏 🧰 👈 ⚙️ **🏃 📋 🔛 🕴** ⚙️ 🍵 🏧 **⏏**.
+
+🖼, 👉 💪 🍵:
+
+* ☁
+* Kubernete
+* ☁ ✍
+* ☁ 🐝 📳
+* ✳
+* 👨💻
+* 🍵 🔘 ☁ 🐕🦺 🍕 👫 🐕🦺
+* 🎏...
+
+## 🧬 - 🛠️ & 💾
+
+⏮️ FastAPI 🈸, ⚙️ 💽 📋 💖 Uvicorn, 🏃♂ ⚫️ 🕐 **1️⃣ 🛠️** 💪 🍦 💗 👩💻 🔁.
+
+✋️ 📚 💼, 👆 🔜 💚 🏃 📚 👨🏭 🛠️ 🎏 🕰.
+
+### 💗 🛠️ - 👨🏭
+
+🚥 👆 ✔️ 🌅 👩💻 🌘 ⚫️❔ 👁 🛠️ 💪 🍵 (🖼 🚥 🕹 🎰 🚫 💁♂️ 🦏) & 👆 ✔️ **💗 🐚** 💽 💽, ⤴️ 👆 💪 ✔️ **💗 🛠️** 🏃♂ ⏮️ 🎏 🈸 🎏 🕰, & 📎 🌐 📨 👪 👫.
+
+🕐❔ 👆 🏃 **💗 🛠️** 🎏 🛠️ 📋, 👫 🛎 🤙 **👨🏭**.
+
+### 👨🏭 🛠️ & ⛴
+
+💭 ⚪️➡️ 🩺 [🔃 🇺🇸🔍](./https.md){.internal-link target=_blank} 👈 🕴 1️⃣ 🛠️ 💪 👂 🔛 1️⃣ 🌀 ⛴ & 📢 📢 💽 ❓
+
+👉 ☑.
+
+, 💪 ✔️ **💗 🛠️** 🎏 🕰, 📤 ✔️ **👁 🛠️ 👂 🔛 ⛴** 👈 ⤴️ 📶 📻 🔠 👨🏭 🛠️ 🌌.
+
+### 💾 📍 🛠️
+
+🔜, 🕐❔ 📋 📐 👜 💾, 🖼, 🎰 🏫 🏷 🔢, ⚖️ 🎚 ⭕ 📁 🔢, 🌐 👈 **🍴 👄 💾 (💾)** 💽.
+
+& 💗 🛠️ 🛎 **🚫 💰 🙆 💾**. 👉 ⛓ 👈 🔠 🏃 🛠️ ✔️ 🚮 👍 👜, 🔢, & 💾. & 🚥 👆 😩 ⭕ 💸 💾 👆 📟, **🔠 🛠️** 🔜 🍴 🌓 💸 💾.
+
+### 💽 💾
+
+🖼, 🚥 👆 📟 📐 🎰 🏫 🏷 ⏮️ **1️⃣ 💾 📐**, 🕐❔ 👆 🏃 1️⃣ 🛠️ ⏮️ 👆 🛠️, ⚫️ 🔜 🍴 🌘 1️⃣ 💾 💾. & 🚥 👆 ▶️ **4️⃣ 🛠️** (4️⃣ 👨🏭), 🔠 🔜 🍴 1️⃣ 💾 💾. 🌐, 👆 🛠️ 🔜 🍴 **4️⃣ 💾 💾**.
+
+& 🚥 👆 🛰 💽 ⚖️ 🕹 🎰 🕴 ✔️ 3️⃣ 💾 💾, 🔄 📐 🌅 🌘 4️⃣ 💾 💾 🔜 🤕 ⚠. 👶
+
+### 💗 🛠️ - 🖼
+
+👉 🖼, 📤 **👨💼 🛠️** 👈 ▶️ & 🎛 2️⃣ **👨🏭 🛠️**.
+
+👉 👨💼 🛠️ 🔜 🎲 1️⃣ 👂 🔛 **⛴** 📢. & ⚫️ 🔜 📶 🌐 📻 👨🏭 🛠️.
+
+👈 👨🏭 🛠️ 🔜 🕐 🏃♂ 👆 🈸, 👫 🔜 🎭 👑 📊 📨 **📨** & 📨 **📨**, & 👫 🔜 📐 🕳 👆 🚮 🔢 💾.
+
+
+
+## 🛠️ 📢 🔐
+
+🔢, 🪔 🔜 🍵 🤝 ⚙️ 🍪 👆 🏧.
+
+✋️ 🕐 👆 🔜, 👆 💪 ⚒ ⚫️ 📢 ⏮️:
+
+
+
+## 💡 🌅
+
+☝, 👆 🔜 🎲 💚 🏪 💽 👆 📱 🌌 👈 😣 🔘 🕰. 👈 👆 💪 ⚙️ 🪔 🧢, ⚫️ ✔️ 👍 **🆓 🎚**.
+
+👆 💪 ✍ 🌅 🪔 🩺.
+
+## 🛠️ 🔧
+
+👟 🔙 🔧 👥 🔬 [🛠️ 🔧](./concepts.md){.internal-link target=_blank}, 📥 ❔ 🔠 👫 🔜 🍵 ⏮️ 🪔:
+
+* **🇺🇸🔍**: 🍵 🪔, 👫 🔜 🤝 👆 📁 & 🍵 🇺🇸🔍 🔁.
+* **🏃♂ 🔛 🕴**: 🍵 🪔, 🍕 👫 🐕🦺.
+* **⏏**: 🍵 🪔, 🍕 👫 🐕🦺.
+* **🧬**: 🍵 🪔, 🍕 👫 🐕🦺.
+* **💾**: 📉 🔁 🪔, 👆 💪 📧 👫 📈 ⚫️.
+* **⏮️ 🔁 ⏭ ▶️**: 🚫 🔗 🐕🦺, 👆 💪 ⚒ ⚫️ 👷 ⏮️ 👫 💾 ⚙️ ⚖️ 🌖 ✍.
+
+!!! note
+ 🪔 🔧 ⚒ ⚫️ ⏩ (& 🆓) 🛠️ 🙅 🈸 🔜.
+
+ ⚫️ 💪 📉 📚 ⚙️ 💼, ✋️ 🎏 🕰, ⚫️ 🚫 🐕🦺 🎏, 💖 ⚙️ 🔢 💽 (↖️ ⚪️➡️ 🪔 👍 ☁ 💽 ⚙️), 🛃 🕹 🎰, ♒️.
+
+ 👆 💪 ✍ 🌅 ℹ 🪔 🩺 👀 🚥 ⚫️ ▶️️ ⚒ 👆.
diff --git a/docs/em/docs/deployment/docker.md b/docs/em/docs/deployment/docker.md
new file mode 100644
index 000000000..51ece5599
--- /dev/null
+++ b/docs/em/docs/deployment/docker.md
@@ -0,0 +1,698 @@
+# FastAPI 📦 - ☁
+
+🕐❔ 🛠️ FastAPI 🈸 ⚠ 🎯 🏗 **💾 📦 🖼**. ⚫️ 🛎 🔨 ⚙️ **☁**. 👆 💪 ⤴️ 🛠️ 👈 📦 🖼 1️⃣ 👩❤👨 💪 🌌.
+
+⚙️ 💾 📦 ✔️ 📚 📈 ✅ **💂♂**, **🔬**, **🦁**, & 🎏.
+
+!!! tip
+ 🏃 & ⏪ 💭 👉 💩 ❓ 🦘 [`Dockerfile` 🔛 👶](#build-a-docker-image-for-fastapi).
+
++ +**FastAPI** 🚫🔜 🔀 🚥 🚫 ⏮️ 👷 🎏. + +📤 ✔️ 📚 🧰 ✍ ⏭ 👈 ✔️ ℹ 😮 🚮 🏗. + +👤 ✔️ ❎ 🏗 🆕 🛠️ 📚 1️⃣2️⃣🗓️. 🥇 👤 🔄 ❎ 🌐 ⚒ 📔 **FastAPI** ⚙️ 📚 🎏 🛠️, 🔌-🔌, & 🧰. + +✋️ ☝, 📤 🙅♂ 🎏 🎛 🌘 🏗 🕳 👈 🚚 🌐 👫 ⚒, ✊ 🏆 💭 ⚪️➡️ ⏮️ 🧰, & 🌀 👫 🏆 🌌 💪, ⚙️ 🇪🇸 ⚒ 👈 ➖🚫 💪 ⏭ (🐍 3️⃣.6️⃣ ➕ 🆎 🔑). + ++ +## 🔬 + +⚙️ 🌐 ⏮️ 🎛 👤 ✔️ 🤞 💡 ⚪️➡️ 🌐 👫, ✊ 💭, & 🌀 👫 🏆 🌌 👤 💪 🔎 👤 & 🏉 👩💻 👤 ✔️ 👷 ⏮️. + +🖼, ⚫️ 🆑 👈 🎲 ⚫️ 🔜 ⚓️ 🔛 🐩 🐍 🆎 🔑. + +, 🏆 🎯 ⚙️ ⏪ ♻ 🐩. + +, ⏭ ▶️ 📟 **FastAPI**, 👤 💸 📚 🗓️ 🎓 🔌 🗄, 🎻 🔗, Oauth2️⃣, ♒️. 🎯 👫 💛, 🔀, & 🔺. + +## 🔧 + +⤴️ 👤 💸 🕰 🔧 👩💻 "🛠️" 👤 💚 ✔️ 👩💻 (👩💻 ⚙️ FastAPI). + +👤 💯 📚 💭 🏆 🌟 🐍 👨🎨: 🗒, 🆚 📟, 🎠 🧢 👨🎨. + +🏁 🐍 👩💻 🔬, 👈 📔 🔃 8️⃣0️⃣ 💯 👩💻. + +⚫️ ⛓ 👈 **FastAPI** 🎯 💯 ⏮️ 👨🎨 ⚙️ 8️⃣0️⃣ 💯 🐍 👩💻. & 🏆 🎏 👨🎨 😑 👷 ➡, 🌐 🚮 💰 🔜 👷 🌖 🌐 👨🎨. + +👈 🌌 👤 💪 🔎 🏆 🌌 📉 📟 ❎ 🌅 💪, ✔️ 🛠️ 🌐, 🆎 & ❌ ✅, ♒️. + +🌐 🌌 👈 🚚 🏆 🛠️ 💡 🌐 👩💻. + +## 📄 + +⏮️ 🔬 📚 🎛, 👤 💭 👈 👤 🔜 ⚙️ **Pydantic** 🚮 📈. + +⤴️ 👤 📉 ⚫️, ⚒ ⚫️ 🍕 🛠️ ⏮️ 🎻 🔗, 🐕🦺 🎏 🌌 🔬 ⚛ 📄, & 📉 👨🎨 🐕🦺 (🆎 ✅, ✍) ⚓️ 🔛 💯 📚 👨🎨. + +⏮️ 🛠️, 👤 📉 **💃**, 🎏 🔑 📄. + +## 🛠️ + +🕰 👤 ▶️ 🏗 **FastAPI** ⚫️, 🏆 🍖 ⏪ 🥉, 🔧 🔬, 📄 & 🧰 🔜, & 💡 🔃 🐩 & 🔧 🆑 & 🍋. + +## 🔮 + +👉 ☝, ⚫️ ⏪ 🆑 👈 **FastAPI** ⏮️ 🚮 💭 ➖ ⚠ 📚 👫👫. + +⚫️ 💆♂ 👐 🤭 ⏮️ 🎛 ♣ 📚 ⚙️ 💼 👍. + +📚 👩💻 & 🏉 ⏪ 🪀 🔛 **FastAPI** 👫 🏗 (🔌 👤 & 👇 🏉). + +✋️, 📤 📚 📈 & ⚒ 👟. + +**FastAPI** ✔️ 👑 🔮 ⤴️. + +& [👆 ℹ](help-fastapi.md){.internal-link target=_blank} 📉 👍. diff --git a/docs/em/docs/index.md b/docs/em/docs/index.md new file mode 100644 index 000000000..ea8a9d41c --- /dev/null +++ b/docs/em/docs/index.md @@ -0,0 +1,469 @@ + +
+ FastAPI 🛠️, ↕ 🎭, ⏩ 💡, ⏩ 📟, 🔜 🏭 +
+ + +--- + +**🧾**: https://fastapi.tiangolo.com + +**ℹ 📟**: https://github.com/tiangolo/fastapi + +--- + +FastAPI 🏛, ⏩ (↕-🎭), 🕸 🛠️ 🏗 🛠️ ⏮️ 🐍 3️⃣.7️⃣ ➕ ⚓️ 🔛 🐩 🐍 🆎 🔑. + +🔑 ⚒: + +* **⏩**: 📶 ↕ 🎭, 🔛 🇷🇪 ⏮️ **✳** & **🚶** (👏 💃 & Pydantic). [1️⃣ ⏩ 🐍 🛠️ 💪](#performance). +* **⏩ 📟**: 📈 🚅 🛠️ ⚒ 🔃 2️⃣0️⃣0️⃣ 💯 3️⃣0️⃣0️⃣ 💯. * +* **👩❤👨 🐛**: 📉 🔃 4️⃣0️⃣ 💯 🗿 (👩💻) 📉 ❌. * +* **🏋️**: 👑 👨🎨 🐕🦺. 🛠️ 🌐. 🌘 🕰 🛠️. +* **⏩**: 🔧 ⏩ ⚙️ & 💡. 🌘 🕰 👂 🩺. +* **📏**: 📉 📟 ❎. 💗 ⚒ ⚪️➡️ 🔠 🔢 📄. 👩❤👨 🐛. +* **🏋️**: 🤚 🏭-🔜 📟. ⏮️ 🏧 🎓 🧾. +* **🐩-⚓️**: ⚓️ 🔛 (& 🍕 🔗 ⏮️) 📂 🐩 🔗: 🗄 (⏪ 💭 🦁) & 🎻 🔗. + +* ⚖ ⚓️ 🔛 💯 🔛 🔗 🛠️ 🏉, 🏗 🏭 🈸. + +## 💰 + + + +{% if sponsors %} +{% for sponsor in sponsors.gold -%} +async def...uvicorn main:app --reload...ujson - ⏩ 🎻 "🎻".
+* email_validator - 📧 🔬.
+
+⚙️ 💃:
+
+* httpx - ✔ 🚥 👆 💚 ⚙️ `TestClient`.
+* jinja2 - ✔ 🚥 👆 💚 ⚙️ 🔢 📄 📳.
+* python-multipart - ✔ 🚥 👆 💚 🐕🦺 📨 "✍", ⏮️ `request.form()`.
+* itsdangerous - ✔ `SessionMiddleware` 🐕🦺.
+* pyyaml - ✔ 💃 `SchemaGenerator` 🐕🦺 (👆 🎲 🚫 💪 ⚫️ ⏮️ FastAPI).
+* ujson - ✔ 🚥 👆 💚 ⚙️ `UJSONResponse`.
+
+⚙️ FastAPI / 💃:
+
+* uvicorn - 💽 👈 📐 & 🍦 👆 🈸.
+* orjson - ✔ 🚥 👆 💚 ⚙️ `ORJSONResponse`.
+
+👆 💪 ❎ 🌐 👫 ⏮️ `pip install "fastapi[all]"`.
+
+## 🛂
+
+👉 🏗 ® 🔽 ⚖ 🇩🇪 🛂.
diff --git a/docs/em/docs/project-generation.md b/docs/em/docs/project-generation.md
new file mode 100644
index 000000000..5fd667ad1
--- /dev/null
+++ b/docs/em/docs/project-generation.md
@@ -0,0 +1,84 @@
+# 🏗 ⚡ - 📄
+
+👆 💪 ⚙️ 🏗 🚂 🤚 ▶️, ⚫️ 🔌 📚 ▶️ ⚒ 🆙, 💂♂, 💽 & 🛠️ 🔗 ⏪ ⌛ 👆.
+
+🏗 🚂 🔜 🕧 ✔️ 📶 🙃 🖥 👈 👆 🔜 ℹ & 🛠️ 👆 👍 💪, ✋️ ⚫️ 💪 👍 ▶️ ☝ 👆 🏗.
+
+## 🌕 📚 FastAPI ✳
+
+📂: https://github.com/tiangolo/full-stack-fastapi-postgresql
+
+### 🌕 📚 FastAPI ✳ - ⚒
+
+* 🌕 **☁** 🛠️ (☁ 🧢).
+* ☁ 🐝 📳 🛠️.
+* **☁ ✍** 🛠️ & 🛠️ 🇧🇿 🛠️.
+* **🏭 🔜** 🐍 🕸 💽 ⚙️ Uvicorn & 🐁.
+* 🐍 **FastAPI** 👩💻:
+ * **⏩**: 📶 ↕ 🎭, 🔛 🇷🇪 ⏮️ **✳** & **🚶** (👏 💃 & Pydantic).
+ * **🏋️**: 👑 👨🎨 🐕🦺. 🛠️ 🌐. 🌘 🕰 🛠️.
+ * **⏩**: 🔧 ⏩ ⚙️ & 💡. 🌘 🕰 👂 🩺.
+ * **📏**: 📉 📟 ❎. 💗 ⚒ ⚪️➡️ 🔠 🔢 📄.
+ * **🏋️**: 🤚 🏭-🔜 📟. ⏮️ 🏧 🎓 🧾.
+ * **🐩-⚓️**: ⚓️ 🔛 (& 🍕 🔗 ⏮️) 📂 🐩 🔗: 🗄 & 🎻 🔗.
+ * **📚 🎏 ⚒** 🔌 🏧 🔬, 🛠️, 🎓 🧾, 🤝 ⏮️ Oauth2️⃣ 🥙 🤝, ♒️.
+* **🔐 🔐** 🔁 🔢.
+* **🥙 🤝** 🤝.
+* **🇸🇲** 🏷 (🔬 🏺 ↔, 👫 💪 ⚙️ ⏮️ 🥒 👨🏭 🔗).
+* 🔰 ▶️ 🏷 👩💻 (🔀 & ❎ 👆 💪).
+* **⚗** 🛠️.
+* **⚜** (✖️ 🇨🇳 ℹ 🤝).
+* **🥒** 👨🏭 👈 💪 🗄 & ⚙️ 🏷 & 📟 ⚪️➡️ 🎂 👩💻 🍕.
+* 🎂 👩💻 💯 ⚓️ 🔛 **✳**, 🛠️ ⏮️ ☁, 👆 💪 💯 🌕 🛠️ 🔗, 🔬 🔛 💽. ⚫️ 🏃 ☁, ⚫️ 💪 🏗 🆕 💽 🏪 ⚪️➡️ 🖌 🔠 🕰 (👆 💪 ⚙️ ✳, ✳, ✳, ⚖️ ⚫️❔ 👆 💚, & 💯 👈 🛠️ 👷).
+* ⏩ 🐍 🛠️ ⏮️ **📂 💾** 🛰 ⚖️-☁ 🛠️ ⏮️ ↔ 💖 ⚛ ⚗ ⚖️ 🎙 🎙 📟 📂.
+* **🎦** 🕸:
+ * 🏗 ⏮️ 🎦 ✳.
+ * **🥙 🤝** 🚚.
+ * 💳 🎑.
+ * ⏮️ 💳, 👑 🕹 🎑.
+ * 👑 🕹 ⏮️ 👩💻 🏗 & 📕.
+ * 👤 👩💻 📕.
+ * **🇷🇪**.
+ * **🎦-📻**.
+ * **Vuetify** 🌹 🧽 🔧 🦲.
+ * **📕**.
+ * ☁ 💽 ⚓️ 🔛 **👌** (📶 🤾 🎆 ⏮️ 🎦-📻).
+ * ☁ 👁-▶️ 🏗, 👆 🚫 💪 🖊 ⚖️ 💕 ✍ 📟.
+ * 🕸 💯 🏃 🏗 🕰 (💪 🔕 💁♂️).
+ * ⚒ 🔧 💪, ⚫️ 👷 👅 📦, ✋️ 👆 💪 🏤-🏗 ⏮️ 🎦 ✳ ⚖️ ✍ ⚫️ 👆 💪, & 🏤-⚙️ ⚫️❔ 👆 💚.
+* ** *️⃣ ** ✳ 💽, 👆 💪 🔀 ⚫️ ⚙️ 📁 & ✳ 💪.
+* **🥀** 🥒 👨🏭 ⚖.
+* 📐 ⚖ 🖖 🕸 & 👩💻 ⏮️ **Traefik**, 👆 💪 ✔️ 👯♂️ 🔽 🎏 🆔, 👽 ➡, ✋️ 🍦 🎏 📦.
+* Traefik 🛠️, ✅ ➡️ 🗜 **🇺🇸🔍** 📄 🏧 ⚡.
+* ✳ **🆑** (🔁 🛠️), 🔌 🕸 & 👩💻 🔬.
+
+## 🌕 📚 FastAPI 🗄
+
+📂: https://github.com/tiangolo/full-stack-fastapi-couchbase
+
+👶 👶 **⚠** 👶 👶
+
+🚥 👆 ▶️ 🆕 🏗 ⚪️➡️ 🖌, ✅ 🎛 📥.
+
+🖼, 🏗 🚂 🌕 📚 FastAPI ✳ 💪 👍 🎛, ⚫️ 🎯 🚧 & ⚙️. & ⚫️ 🔌 🌐 🆕 ⚒ & 📈.
+
+👆 🆓 ⚙️ 🗄-⚓️ 🚂 🚥 👆 💚, ⚫️ 🔜 🎲 👷 👌, & 🚥 👆 ⏪ ✔️ 🏗 🏗 ⏮️ ⚫️ 👈 👌 👍 (& 👆 🎲 ⏪ ℹ ⚫️ ♣ 👆 💪).
+
+👆 💪 ✍ 🌅 🔃 ⚫️ 🩺 🏦.
+
+## 🌕 📚 FastAPI ✳
+
+...💪 👟 ⏪, ⚓️ 🔛 👇 🕰 🚚 & 🎏 ⚖. 👶 👶
+
+## 🎰 🏫 🏷 ⏮️ 🌈 & FastAPI
+
+📂: https://github.com/microsoft/cookiecutter-spacy-fastapi
+
+### 🎰 🏫 🏷 ⏮️ 🌈 & FastAPI - ⚒
+
+* **🌈** 🕜 🏷 🛠️.
+* **☁ 🧠 🔎** 📨 📁 🏗.
+* **🏭 🔜** 🐍 🕸 💽 ⚙️ Uvicorn & 🐁.
+* **☁ 👩💻** Kubernete (🦲) 🆑/💿 🛠️ 🏗.
+* **🤸♂** 💪 ⚒ 1️⃣ 🌈 🏗 🇪🇸 ⏮️ 🏗 🖥.
+* **💪 🏧** 🎏 🏷 🛠️ (Pytorch, 🇸🇲), 🚫 🌈.
diff --git a/docs/em/docs/python-types.md b/docs/em/docs/python-types.md
new file mode 100644
index 000000000..e079d9039
--- /dev/null
+++ b/docs/em/docs/python-types.md
@@ -0,0 +1,490 @@
+# 🐍 🆎 🎶
+
+🐍 ✔️ 🐕🦺 📦 "🆎 🔑".
+
+👫 **"🆎 🔑"** 🎁 ❕ 👈 ✔ 📣 🆎 🔢.
+
+📣 🆎 👆 🔢, 👨🎨 & 🧰 💪 🤝 👆 👍 🐕🦺.
+
+👉 **⏩ 🔰 / ↗️** 🔃 🐍 🆎 🔑. ⚫️ 📔 🕴 💯 💪 ⚙️ 👫 ⏮️ **FastAPI**... ❔ 🤙 📶 🐥.
+
+**FastAPI** 🌐 ⚓️ 🔛 👫 🆎 🔑, 👫 🤝 ⚫️ 📚 📈 & 💰.
+
+✋️ 🚥 👆 🙅 ⚙️ **FastAPI**, 👆 🔜 💰 ⚪️➡️ 🏫 🍖 🔃 👫.
+
+!!! note
+ 🚥 👆 🐍 🕴, & 👆 ⏪ 💭 🌐 🔃 🆎 🔑, 🚶 ⏭ 📃.
+
+## 🎯
+
+➡️ ▶️ ⏮️ 🙅 🖼:
+
+```Python
+{!../../../docs_src/python_types/tutorial001.py!}
+```
+
+🤙 👉 📋 🔢:
+
+```
+John Doe
+```
+
+🔢 🔨 📄:
+
+* ✊ `first_name` & `last_name`.
+* 🗜 🥇 🔤 🔠 1️⃣ ↖ 💼 ⏮️ `title()`.
+* 🔢 👫 ⏮️ 🚀 🖕.
+
+```Python hl_lines="2"
+{!../../../docs_src/python_types/tutorial001.py!}
+```
+
+### ✍ ⚫️
+
+⚫️ 📶 🙅 📋.
+
+✋️ 🔜 🌈 👈 👆 ✍ ⚫️ ⚪️➡️ 🖌.
+
+☝ 👆 🔜 ✔️ ▶️ 🔑 🔢, 👆 ✔️ 🔢 🔜...
+
+✋️ ⤴️ 👆 ✔️ 🤙 "👈 👩🔬 👈 🗜 🥇 🔤 ↖ 💼".
+
+⚫️ `upper`❓ ⚫️ `uppercase`❓ `first_uppercase`❓ `capitalize`❓
+
+⤴️, 👆 🔄 ⏮️ 🗝 👩💻 👨👧👦, 👨🎨 ✍.
+
+👆 🆎 🥇 🔢 🔢, `first_name`, ⤴️ ❣ (`.`) & ⤴️ 🎯 `Ctrl+Space` ⏲ 🛠️.
+
+✋️, 😞, 👆 🤚 🕳 ⚠:
+
+
+
+### 🚮 🆎
+
+➡️ 🔀 👁 ⏸ ⚪️➡️ ⏮️ ⏬.
+
+👥 🔜 🔀 ⚫️❔ 👉 🧬, 🔢 🔢, ⚪️➡️:
+
+```Python
+ first_name, last_name
+```
+
+:
+
+```Python
+ first_name: str, last_name: str
+```
+
+👈 ⚫️.
+
+👈 "🆎 🔑":
+
+```Python hl_lines="1"
+{!../../../docs_src/python_types/tutorial002.py!}
+```
+
+👈 🚫 🎏 📣 🔢 💲 💖 🔜 ⏮️:
+
+```Python
+ first_name="john", last_name="doe"
+```
+
+⚫️ 🎏 👜.
+
+👥 ⚙️ ❤ (`:`), 🚫 🌓 (`=`).
+
+& ❎ 🆎 🔑 🛎 🚫 🔀 ⚫️❔ 🔨 ⚪️➡️ ⚫️❔ 🔜 🔨 🍵 👫.
+
+✋️ 🔜, 🌈 👆 🔄 🖕 🏗 👈 🔢, ✋️ ⏮️ 🆎 🔑.
+
+🎏 ☝, 👆 🔄 ⏲ 📋 ⏮️ `Ctrl+Space` & 👆 👀:
+
+
+
+⏮️ 👈, 👆 💪 📜, 👀 🎛, ⏭ 👆 🔎 1️⃣ 👈 "💍 🔔":
+
+
+
+## 🌅 🎯
+
+✅ 👉 🔢, ⚫️ ⏪ ✔️ 🆎 🔑:
+
+```Python hl_lines="1"
+{!../../../docs_src/python_types/tutorial003.py!}
+```
+
+↩️ 👨🎨 💭 🆎 🔢, 👆 🚫 🕴 🤚 🛠️, 👆 🤚 ❌ ✅:
+
+
+
+🔜 👆 💭 👈 👆 ✔️ 🔧 ⚫️, 🗜 `age` 🎻 ⏮️ `str(age)`:
+
+```Python hl_lines="2"
+{!../../../docs_src/python_types/tutorial004.py!}
+```
+
+## 📣 🆎
+
+👆 👀 👑 🥉 📣 🆎 🔑. 🔢 🔢.
+
+👉 👑 🥉 👆 🔜 ⚙️ 👫 ⏮️ **FastAPI**.
+
+### 🙅 🆎
+
+👆 💪 📣 🌐 🐩 🐍 🆎, 🚫 🕴 `str`.
+
+👆 💪 ⚙️, 🖼:
+
+* `int`
+* `float`
+* `bool`
+* `bytes`
+
+```Python hl_lines="1"
+{!../../../docs_src/python_types/tutorial005.py!}
+```
+
+### 💊 🆎 ⏮️ 🆎 🔢
+
+📤 📊 📊 👈 💪 🔌 🎏 💲, 💖 `dict`, `list`, `set` & `tuple`. & 🔗 💲 💪 ✔️ 👫 👍 🆎 💁♂️.
+
+👉 🆎 👈 ✔️ 🔗 🆎 🤙 "**💊**" 🆎. & ⚫️ 💪 📣 👫, ⏮️ 👫 🔗 🆎.
+
+📣 👈 🆎 & 🔗 🆎, 👆 💪 ⚙️ 🐩 🐍 🕹 `typing`. ⚫️ 🔀 🎯 🐕🦺 👫 🆎 🔑.
+
+#### 🆕 ⏬ 🐍
+
+❕ ⚙️ `typing` **🔗** ⏮️ 🌐 ⏬, ⚪️➡️ 🐍 3️⃣.6️⃣ ⏪ 🕐, ✅ 🐍 3️⃣.9️⃣, 🐍 3️⃣.1️⃣0️⃣, ♒️.
+
+🐍 🏧, **🆕 ⏬** 👟 ⏮️ 📉 🐕🦺 👉 🆎 ✍ & 📚 💼 👆 🏆 🚫 💪 🗄 & ⚙️ `typing` 🕹 📣 🆎 ✍.
+
+🚥 👆 💪 ⚒ 🌖 ⏮️ ⏬ 🐍 👆 🏗, 👆 🔜 💪 ✊ 📈 👈 ➕ 🦁. 👀 🖼 🔛.
+
+#### 📇
+
+🖼, ➡️ 🔬 🔢 `list` `str`.
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ⚪️➡️ `typing`, 🗄 `List` (⏮️ 🔠 `L`):
+
+ ``` Python hl_lines="1"
+ {!> ../../../docs_src/python_types/tutorial006.py!}
+ ```
+
+ 📣 🔢, ⏮️ 🎏 ❤ (`:`) ❕.
+
+ 🆎, 🚮 `List` 👈 👆 🗄 ⚪️➡️ `typing`.
+
+ 📇 🆎 👈 🔌 🔗 🆎, 👆 🚮 👫 ⬜ 🗜:
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/python_types/tutorial006.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ 📣 🔢, ⏮️ 🎏 ❤ (`:`) ❕.
+
+ 🆎, 🚮 `list`.
+
+ 📇 🆎 👈 🔌 🔗 🆎, 👆 🚮 👫 ⬜ 🗜:
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/python_types/tutorial006_py39.py!}
+ ```
+
+!!! info
+ 👈 🔗 🆎 ⬜ 🗜 🤙 "🆎 🔢".
+
+ 👉 💼, `str` 🆎 🔢 🚶♀️ `List` (⚖️ `list` 🐍 3️⃣.9️⃣ & 🔛).
+
+👈 ⛓: "🔢 `items` `list`, & 🔠 🏬 👉 📇 `str`".
+
+!!! tip
+ 🚥 👆 ⚙️ 🐍 3️⃣.9️⃣ ⚖️ 🔛, 👆 🚫 ✔️ 🗄 `List` ⚪️➡️ `typing`, 👆 💪 ⚙️ 🎏 🥔 `list` 🆎 ↩️.
+
+🔨 👈, 👆 👨🎨 💪 🚚 🐕🦺 ⏪ 🏭 🏬 ⚪️➡️ 📇:
+
+
+
+🍵 🆎, 👈 🌖 💪 🏆.
+
+👀 👈 🔢 `item` 1️⃣ 🔣 📇 `items`.
+
+& , 👨🎨 💭 ⚫️ `str`, & 🚚 🐕🦺 👈.
+
+#### 🔢 & ⚒
+
+👆 🔜 🎏 📣 `tuple`Ⓜ & `set`Ⓜ:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="1 4"
+ {!> ../../../docs_src/python_types/tutorial007.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/python_types/tutorial007_py39.py!}
+ ```
+
+👉 ⛓:
+
+* 🔢 `items_t` `tuple` ⏮️ 3️⃣ 🏬, `int`, ➕1️⃣ `int`, & `str`.
+* 🔢 `items_s` `set`, & 🔠 🚮 🏬 🆎 `bytes`.
+
+#### #️⃣
+
+🔬 `dict`, 👆 🚶♀️ 2️⃣ 🆎 🔢, 🎏 ❕.
+
+🥇 🆎 🔢 🔑 `dict`.
+
+🥈 🆎 🔢 💲 `dict`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="1 4"
+ {!> ../../../docs_src/python_types/tutorial008.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/python_types/tutorial008_py39.py!}
+ ```
+
+👉 ⛓:
+
+* 🔢 `prices` `dict`:
+ * 🔑 👉 `dict` 🆎 `str` (➡️ 💬, 📛 🔠 🏬).
+ * 💲 👉 `dict` 🆎 `float` (➡️ 💬, 🔖 🔠 🏬).
+
+#### 🇪🇺
+
+👆 💪 📣 👈 🔢 💪 🙆 **📚 🆎**, 🖼, `int` ⚖️ `str`.
+
+🐍 3️⃣.6️⃣ & 🔛 (✅ 🐍 3️⃣.1️⃣0️⃣) 👆 💪 ⚙️ `Union` 🆎 ⚪️➡️ `typing` & 🚮 🔘 ⬜ 🗜 💪 🆎 🚫.
+
+🐍 3️⃣.1️⃣0️⃣ 📤 **🎛 ❕** 🌐❔ 👆 💪 🚮 💪 🆎 👽 ⏸ ⏸ (`|`).
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="1 4"
+ {!> ../../../docs_src/python_types/tutorial008b.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/python_types/tutorial008b_py310.py!}
+ ```
+
+👯♂️ 💼 👉 ⛓ 👈 `item` 💪 `int` ⚖️ `str`.
+
+#### 🎲 `None`
+
+👆 💪 📣 👈 💲 💪 ✔️ 🆎, 💖 `str`, ✋️ 👈 ⚫️ 💪 `None`.
+
+🐍 3️⃣.6️⃣ & 🔛 (✅ 🐍 3️⃣.1️⃣0️⃣) 👆 💪 📣 ⚫️ 🏭 & ⚙️ `Optional` ⚪️➡️ `typing` 🕹.
+
+```Python hl_lines="1 4"
+{!../../../docs_src/python_types/tutorial009.py!}
+```
+
+⚙️ `Optional[str]` ↩️ `str` 🔜 ➡️ 👨🎨 ℹ 👆 🔍 ❌ 🌐❔ 👆 💪 🤔 👈 💲 🕧 `str`, 🕐❔ ⚫️ 💪 🤙 `None` 💁♂️.
+
+`Optional[Something]` 🤙 ⌨ `Union[Something, None]`, 👫 🌓.
+
+👉 ⛓ 👈 🐍 3️⃣.1️⃣0️⃣, 👆 💪 ⚙️ `Something | None`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="1 4"
+ {!> ../../../docs_src/python_types/tutorial009.py!}
+ ```
+
+=== "🐍 3️⃣.6️⃣ & 🔛 - 🎛"
+
+ ```Python hl_lines="1 4"
+ {!> ../../../docs_src/python_types/tutorial009b.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/python_types/tutorial009_py310.py!}
+ ```
+
+#### ⚙️ `Union` ⚖️ `Optional`
+
+🚥 👆 ⚙️ 🐍 ⏬ 🔛 3️⃣.1️⃣0️⃣, 📥 💁♂ ⚪️➡️ 👇 📶 **🤔** ☝ 🎑:
+
+* 👶 ❎ ⚙️ `Optional[SomeType]`
+* ↩️ 👶 **⚙️ `Union[SomeType, None]`** 👶.
+
+👯♂️ 🌓 & 🔘 👫 🎏, ✋️ 👤 🔜 👍 `Union` ↩️ `Optional` ↩️ 🔤 "**📦**" 🔜 😑 🔑 👈 💲 📦, & ⚫️ 🤙 ⛓ "⚫️ 💪 `None`", 🚥 ⚫️ 🚫 📦 & ✔.
+
+👤 💭 `Union[SomeType, None]` 🌖 🔑 🔃 ⚫️❔ ⚫️ ⛓.
+
+⚫️ 🔃 🔤 & 📛. ✋️ 👈 🔤 💪 📉 ❔ 👆 & 👆 🤽♂ 💭 🔃 📟.
+
+🖼, ➡️ ✊ 👉 🔢:
+
+```Python hl_lines="1 4"
+{!../../../docs_src/python_types/tutorial009c.py!}
+```
+
+🔢 `name` 🔬 `Optional[str]`, ✋️ ⚫️ **🚫 📦**, 👆 🚫🔜 🤙 🔢 🍵 🔢:
+
+```Python
+say_hi() # Oh, no, this throws an error! 😱
+```
+
+`name` 🔢 **✔** (🚫 *📦*) ↩️ ⚫️ 🚫 ✔️ 🔢 💲. , `name` 🚫 `None` 💲:
+
+```Python
+say_hi(name=None) # This works, None is valid 🎉
+```
+
+👍 📰, 🕐 👆 🔛 🐍 3️⃣.1️⃣0️⃣ 👆 🏆 🚫 ✔️ 😟 🔃 👈, 👆 🔜 💪 🎯 ⚙️ `|` 🔬 🇪🇺 🆎:
+
+```Python hl_lines="1 4"
+{!../../../docs_src/python_types/tutorial009c_py310.py!}
+```
+
+& ⤴️ 👆 🏆 🚫 ✔️ 😟 🔃 📛 💖 `Optional` & `Union`. 👶
+
+#### 💊 🆎
+
+👉 🆎 👈 ✊ 🆎 🔢 ⬜ 🗜 🤙 **💊 🆎** ⚖️ **💊**, 🖼:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ * `List`
+ * `Tuple`
+ * `Set`
+ * `Dict`
+ * `Union`
+ * `Optional`
+ * ...& 🎏.
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ 👆 💪 ⚙️ 🎏 💽 🆎 💊 (⏮️ ⬜ 🗜 & 🆎 🔘):
+
+ * `list`
+ * `tuple`
+ * `set`
+ * `dict`
+
+ & 🎏 ⏮️ 🐍 3️⃣.6️⃣, ⚪️➡️ `typing` 🕹:
+
+ * `Union`
+ * `Optional`
+ * ...& 🎏.
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ 👆 💪 ⚙️ 🎏 💽 🆎 💊 (⏮️ ⬜ 🗜 & 🆎 🔘):
+
+ * `list`
+ * `tuple`
+ * `set`
+ * `dict`
+
+ & 🎏 ⏮️ 🐍 3️⃣.6️⃣, ⚪️➡️ `typing` 🕹:
+
+ * `Union`
+ * `Optional` (🎏 ⏮️ 🐍 3️⃣.6️⃣)
+ * ...& 🎏.
+
+ 🐍 3️⃣.1️⃣0️⃣, 🎛 ⚙️ 💊 `Union` & `Optional`, 👆 💪 ⚙️ ⏸ ⏸ (`|`) 📣 🇪🇺 🆎.
+
+### 🎓 🆎
+
+👆 💪 📣 🎓 🆎 🔢.
+
+➡️ 💬 👆 ✔️ 🎓 `Person`, ⏮️ 📛:
+
+```Python hl_lines="1-3"
+{!../../../docs_src/python_types/tutorial010.py!}
+```
+
+⤴️ 👆 💪 📣 🔢 🆎 `Person`:
+
+```Python hl_lines="6"
+{!../../../docs_src/python_types/tutorial010.py!}
+```
+
+& ⤴️, 🔄, 👆 🤚 🌐 👨🎨 🐕🦺:
+
+
+
+## Pydantic 🏷
+
+Pydantic 🐍 🗃 🎭 📊 🔬.
+
+👆 📣 "💠" 💽 🎓 ⏮️ 🔢.
+
+& 🔠 🔢 ✔️ 🆎.
+
+⤴️ 👆 ✍ 👐 👈 🎓 ⏮️ 💲 & ⚫️ 🔜 ✔ 💲, 🗜 👫 ☑ 🆎 (🚥 👈 💼) & 🤝 👆 🎚 ⏮️ 🌐 💽.
+
+& 👆 🤚 🌐 👨🎨 🐕🦺 ⏮️ 👈 📉 🎚.
+
+🖼 ⚪️➡️ 🛂 Pydantic 🩺:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python
+ {!> ../../../docs_src/python_types/tutorial011.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python
+ {!> ../../../docs_src/python_types/tutorial011_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python
+ {!> ../../../docs_src/python_types/tutorial011_py310.py!}
+ ```
+
+!!! info
+ 💡 🌖 🔃 Pydantic, ✅ 🚮 🩺.
+
+**FastAPI** 🌐 ⚓️ 🔛 Pydantic.
+
+👆 🔜 👀 📚 🌅 🌐 👉 💡 [🔰 - 👩💻 🦮](tutorial/index.md){.internal-link target=_blank}.
+
+!!! tip
+ Pydantic ✔️ 🎁 🎭 🕐❔ 👆 ⚙️ `Optional` ⚖️ `Union[Something, None]` 🍵 🔢 💲, 👆 💪 ✍ 🌅 🔃 ⚫️ Pydantic 🩺 🔃 ✔ 📦 🏑.
+
+## 🆎 🔑 **FastAPI**
+
+**FastAPI** ✊ 📈 👫 🆎 🔑 📚 👜.
+
+⏮️ **FastAPI** 👆 📣 🔢 ⏮️ 🆎 🔑 & 👆 🤚:
+
+* **👨🎨 🐕🦺**.
+* **🆎 ✅**.
+
+...and **FastAPI** uses the same declarations :
+
+* **🔬 📄**: ⚪️➡️ 📨 ➡ 🔢, 🔢 🔢, 🎚, 💪, 🔗, ♒️.
+* **🗜 💽**: ⚪️➡️ 📨 🚚 🆎.
+* **✔ 💽**: 👟 ⚪️➡️ 🔠 📨:
+ * 🏭 **🏧 ❌** 📨 👩💻 🕐❔ 📊 ❌.
+* **📄** 🛠️ ⚙️ 🗄:
+ * ❔ ⤴️ ⚙️ 🏧 🎓 🧾 👩💻 🔢.
+
+👉 5️⃣📆 🌐 🔊 📝. 🚫 😟. 👆 🔜 👀 🌐 👉 🎯 [🔰 - 👩💻 🦮](tutorial/index.md){.internal-link target=_blank}.
+
+⚠ 👜 👈 ⚙️ 🐩 🐍 🆎, 👁 🥉 (↩️ ❎ 🌖 🎓, 👨🎨, ♒️), **FastAPI** 🔜 📚 👷 👆.
+
+!!! info
+ 🚥 👆 ⏪ 🚶 🔘 🌐 🔰 & 👟 🔙 👀 🌅 🔃 🆎, 👍 ℹ "🎮 🎼" ⚪️➡️ `mypy`.
diff --git a/docs/em/docs/tutorial/background-tasks.md b/docs/em/docs/tutorial/background-tasks.md
new file mode 100644
index 000000000..e28ead415
--- /dev/null
+++ b/docs/em/docs/tutorial/background-tasks.md
@@ -0,0 +1,102 @@
+# 🖥 📋
+
+👆 💪 🔬 🖥 📋 🏃 *⏮️* 🛬 📨.
+
+👉 ⚠ 🛠️ 👈 💪 🔨 ⏮️ 📨, ✋️ 👈 👩💻 🚫 🤙 ✔️ ⌛ 🛠️ 🏁 ⏭ 📨 📨.
+
+👉 🔌, 🖼:
+
+* 📧 📨 📨 ⏮️ 🎭 🎯:
+ * 🔗 📧 💽 & 📨 📧 😑 "🐌" (📚 🥈), 👆 💪 📨 📨 ▶️️ ↖️ & 📨 📧 📨 🖥.
+* 🏭 💽:
+ * 🖼, ➡️ 💬 👆 📨 📁 👈 🔜 🚶 🔘 🐌 🛠️, 👆 💪 📨 📨 "🚫" (🇺🇸🔍 2️⃣0️⃣2️⃣) & 🛠️ ⚫️ 🖥.
+
+## ⚙️ `BackgroundTasks`
+
+🥇, 🗄 `BackgroundTasks` & 🔬 🔢 👆 *➡ 🛠️ 🔢* ⏮️ 🆎 📄 `BackgroundTasks`:
+
+```Python hl_lines="1 13"
+{!../../../docs_src/background_tasks/tutorial001.py!}
+```
+
+**FastAPI** 🔜 ✍ 🎚 🆎 `BackgroundTasks` 👆 & 🚶♀️ ⚫️ 👈 🔢.
+
+## ✍ 📋 🔢
+
+✍ 🔢 🏃 🖥 📋.
+
+⚫️ 🐩 🔢 👈 💪 📨 🔢.
+
+⚫️ 💪 `async def` ⚖️ 😐 `def` 🔢, **FastAPI** 🔜 💭 ❔ 🍵 ⚫️ ☑.
+
+👉 💼, 📋 🔢 🔜 ✍ 📁 (⚖ 📨 📧).
+
+& ✍ 🛠️ 🚫 ⚙️ `async` & `await`, 👥 🔬 🔢 ⏮️ 😐 `def`:
+
+```Python hl_lines="6-9"
+{!../../../docs_src/background_tasks/tutorial001.py!}
+```
+
+## 🚮 🖥 📋
+
+🔘 👆 *➡ 🛠️ 🔢*, 🚶♀️ 👆 📋 🔢 *🖥 📋* 🎚 ⏮️ 👩🔬 `.add_task()`:
+
+```Python hl_lines="14"
+{!../../../docs_src/background_tasks/tutorial001.py!}
+```
+
+`.add_task()` 📨 ❌:
+
+* 📋 🔢 🏃 🖥 (`write_notification`).
+* 🙆 🔁 ❌ 👈 🔜 🚶♀️ 📋 🔢 ✔ (`email`).
+* 🙆 🇨🇻 ❌ 👈 🔜 🚶♀️ 📋 🔢 (`message="some notification"`).
+
+## 🔗 💉
+
+⚙️ `BackgroundTasks` 👷 ⏮️ 🔗 💉 ⚙️, 👆 💪 📣 🔢 🆎 `BackgroundTasks` 💗 🎚: *➡ 🛠️ 🔢*, 🔗 (☑), 🎧-🔗, ♒️.
+
+**FastAPI** 💭 ⚫️❔ 🔠 💼 & ❔ 🏤-⚙️ 🎏 🎚, 👈 🌐 🖥 📋 🔗 👯♂️ & 🏃 🖥 ⏮️:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="13 15 22 25"
+ {!> ../../../docs_src/background_tasks/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="11 13 20 23"
+ {!> ../../../docs_src/background_tasks/tutorial002_py310.py!}
+ ```
+
+👉 🖼, 📧 🔜 ✍ `log.txt` 📁 *⏮️* 📨 📨.
+
+🚥 📤 🔢 📨, ⚫️ 🔜 ✍ 🕹 🖥 📋.
+
+& ⤴️ ➕1️⃣ 🖥 📋 🏗 *➡ 🛠️ 🔢* 🔜 ✍ 📧 ⚙️ `email` ➡ 🔢.
+
+## 📡 ℹ
+
+🎓 `BackgroundTasks` 👟 🔗 ⚪️➡️ `starlette.background`.
+
+⚫️ 🗄/🔌 🔗 🔘 FastAPI 👈 👆 💪 🗄 ⚫️ ⚪️➡️ `fastapi` & ❎ 😫 🗄 🎛 `BackgroundTask` (🍵 `s` 🔚) ⚪️➡️ `starlette.background`.
+
+🕴 ⚙️ `BackgroundTasks` (& 🚫 `BackgroundTask`), ⚫️ ⤴️ 💪 ⚙️ ⚫️ *➡ 🛠️ 🔢* 🔢 & ✔️ **FastAPI** 🍵 🎂 👆, 💖 🕐❔ ⚙️ `Request` 🎚 🔗.
+
+⚫️ 💪 ⚙️ `BackgroundTask` 😞 FastAPI, ✋️ 👆 ✔️ ✍ 🎚 👆 📟 & 📨 💃 `Response` 🔌 ⚫️.
+
+👆 💪 👀 🌖 ℹ 💃 🛂 🩺 🖥 📋.
+
+## ⚠
+
+🚥 👆 💪 🎭 🏋️ 🖥 📊 & 👆 🚫 🎯 💪 ⚫️ 🏃 🎏 🛠️ (🖼, 👆 🚫 💪 💰 💾, 🔢, ♒️), 👆 💪 💰 ⚪️➡️ ⚙️ 🎏 🦏 🧰 💖 🥒.
+
+👫 😑 🚚 🌖 🏗 📳, 📧/👨🏭 📤 👨💼, 💖 ✳ ⚖️ ✳, ✋️ 👫 ✔ 👆 🏃 🖥 📋 💗 🛠️, & ✴️, 💗 💽.
+
+👀 🖼, ✅ [🏗 🚂](../project-generation.md){.internal-link target=_blank}, 👫 🌐 🔌 🥒 ⏪ 📶.
+
+✋️ 🚥 👆 💪 🔐 🔢 & 🎚 ⚪️➡️ 🎏 **FastAPI** 📱, ⚖️ 👆 💪 🎭 🤪 🖥 📋 (💖 📨 📧 📨), 👆 💪 🎯 ⚙️ `BackgroundTasks`.
+
+## 🌃
+
+🗄 & ⚙️ `BackgroundTasks` ⏮️ 🔢 *➡ 🛠️ 🔢* & 🔗 🚮 🖥 📋.
diff --git a/docs/em/docs/tutorial/bigger-applications.md b/docs/em/docs/tutorial/bigger-applications.md
new file mode 100644
index 000000000..7b4694387
--- /dev/null
+++ b/docs/em/docs/tutorial/bigger-applications.md
@@ -0,0 +1,488 @@
+# 🦏 🈸 - 💗 📁
+
+🚥 👆 🏗 🈸 ⚖️ 🕸 🛠️, ⚫️ 🛎 💼 👈 👆 💪 🚮 🌐 🔛 👁 📁.
+
+**FastAPI** 🚚 🏪 🧰 📊 👆 🈸 ⏪ 🚧 🌐 💪.
+
+!!! info
+ 🚥 👆 👟 ⚪️➡️ 🏺, 👉 🔜 🌓 🏺 📗.
+
+## 🖼 📁 📊
+
+➡️ 💬 👆 ✔️ 📁 📊 💖 👉:
+
+```
+.
+├── app
+│ ├── __init__.py
+│ ├── main.py
+│ ├── dependencies.py
+│ └── routers
+│ │ ├── __init__.py
+│ │ ├── items.py
+│ │ └── users.py
+│ └── internal
+│ ├── __init__.py
+│ └── admin.py
+```
+
+!!! tip
+ 📤 📚 `__init__.py` 📁: 1️⃣ 🔠 📁 ⚖️ 📁.
+
+ 👉 ⚫️❔ ✔ 🏭 📟 ⚪️➡️ 1️⃣ 📁 🔘 ➕1️⃣.
+
+ 🖼, `app/main.py` 👆 💪 ✔️ ⏸ 💖:
+
+ ```
+ from app.routers import items
+ ```
+
+* `app` 📁 🔌 🌐. & ⚫️ ✔️ 🛁 📁 `app/__init__.py`, ⚫️ "🐍 📦" (🗃 "🐍 🕹"): `app`.
+* ⚫️ 🔌 `app/main.py` 📁. ⚫️ 🔘 🐍 📦 (📁 ⏮️ 📁 `__init__.py`), ⚫️ "🕹" 👈 📦: `app.main`.
+* 📤 `app/dependencies.py` 📁, 💖 `app/main.py`, ⚫️ "🕹": `app.dependencies`.
+* 📤 📁 `app/routers/` ⏮️ ➕1️⃣ 📁 `__init__.py`, ⚫️ "🐍 📦": `app.routers`.
+* 📁 `app/routers/items.py` 🔘 📦, `app/routers/`,, ⚫️ 🔁: `app.routers.items`.
+* 🎏 ⏮️ `app/routers/users.py`, ⚫️ ➕1️⃣ 🔁: `app.routers.users`.
+* 📤 📁 `app/internal/` ⏮️ ➕1️⃣ 📁 `__init__.py`, ⚫️ ➕1️⃣ "🐍 📦": `app.internal`.
+* & 📁 `app/internal/admin.py` ➕1️⃣ 🔁: `app.internal.admin`.
+
+
+
+## 🔌 🎏 📻 💗 🕰 ⏮️ 🎏 `prefix`
+
+👆 💪 ⚙️ `.include_router()` 💗 🕰 ⏮️ *🎏* 📻 ⚙️ 🎏 🔡.
+
+👉 💪 ⚠, 🖼, 🎦 🎏 🛠️ 🔽 🎏 🔡, ✅ `/api/v1` & `/api/latest`.
+
+👉 🏧 ⚙️ 👈 👆 5️⃣📆 🚫 🤙 💪, ✋️ ⚫️ 📤 💼 👆.
+
+## 🔌 `APIRouter` ➕1️⃣
+
+🎏 🌌 👆 💪 🔌 `APIRouter` `FastAPI` 🈸, 👆 💪 🔌 `APIRouter` ➕1️⃣ `APIRouter` ⚙️:
+
+```Python
+router.include_router(other_router)
+```
+
+⚒ 💭 👆 ⚫️ ⏭ 🔌 `router` `FastAPI` 📱, 👈 *➡ 🛠️* ⚪️➡️ `other_router` 🔌.
diff --git a/docs/em/docs/tutorial/body-fields.md b/docs/em/docs/tutorial/body-fields.md
new file mode 100644
index 000000000..9f2c914f4
--- /dev/null
+++ b/docs/em/docs/tutorial/body-fields.md
@@ -0,0 +1,68 @@
+# 💪 - 🏑
+
+🎏 🌌 👆 💪 📣 🌖 🔬 & 🗃 *➡ 🛠️ 🔢* 🔢 ⏮️ `Query`, `Path` & `Body`, 👆 💪 📣 🔬 & 🗃 🔘 Pydantic 🏷 ⚙️ Pydantic `Field`.
+
+## 🗄 `Field`
+
+🥇, 👆 ✔️ 🗄 ⚫️:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body_fields/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="2"
+ {!> ../../../docs_src/body_fields/tutorial001_py310.py!}
+ ```
+
+!!! warning
+ 👀 👈 `Field` 🗄 🔗 ⚪️➡️ `pydantic`, 🚫 ⚪️➡️ `fastapi` 🌐 🎂 (`Query`, `Path`, `Body`, ♒️).
+
+## 📣 🏷 🔢
+
+👆 💪 ⤴️ ⚙️ `Field` ⏮️ 🏷 🔢:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="11-14"
+ {!> ../../../docs_src/body_fields/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="9-12"
+ {!> ../../../docs_src/body_fields/tutorial001_py310.py!}
+ ```
+
+`Field` 👷 🎏 🌌 `Query`, `Path` & `Body`, ⚫️ ✔️ 🌐 🎏 🔢, ♒️.
+
+!!! note "📡 ℹ"
+ 🤙, `Query`, `Path` & 🎏 👆 🔜 👀 ⏭ ✍ 🎚 🏿 ⚠ `Param` 🎓, ❔ ⚫️ 🏿 Pydantic `FieldInfo` 🎓.
+
+ & Pydantic `Field` 📨 👐 `FieldInfo` 👍.
+
+ `Body` 📨 🎚 🏿 `FieldInfo` 🔗. & 📤 🎏 👆 🔜 👀 ⏪ 👈 🏿 `Body` 🎓.
+
+ 💭 👈 🕐❔ 👆 🗄 `Query`, `Path`, & 🎏 ⚪️➡️ `fastapi`, 👈 🤙 🔢 👈 📨 🎁 🎓.
+
+!!! tip
+ 👀 ❔ 🔠 🏷 🔢 ⏮️ 🆎, 🔢 💲 & `Field` ✔️ 🎏 📊 *➡ 🛠️ 🔢* 🔢, ⏮️ `Field` ↩️ `Path`, `Query` & `Body`.
+
+## 🚮 ➕ ℹ
+
+👆 💪 📣 ➕ ℹ `Field`, `Query`, `Body`, ♒️. & ⚫️ 🔜 🔌 🏗 🎻 🔗.
+
+👆 🔜 💡 🌅 🔃 ❎ ➕ ℹ ⏪ 🩺, 🕐❔ 🏫 📣 🖼.
+
+!!! warning
+ ➕ 🔑 🚶♀️ `Field` 🔜 🎁 📉 🗄 🔗 👆 🈸.
+ 👫 🔑 5️⃣📆 🚫 🎯 🍕 🗄 🔧, 🗄 🧰, 🖼 [🗄 💳](https://validator.swagger.io/), 5️⃣📆 🚫 👷 ⏮️ 👆 🏗 🔗.
+
+## 🌃
+
+👆 💪 ⚙️ Pydantic `Field` 📣 ➕ 🔬 & 🗃 🏷 🔢.
+
+👆 💪 ⚙️ ➕ 🇨🇻 ❌ 🚶♀️ 🌖 🎻 🔗 🗃.
diff --git a/docs/em/docs/tutorial/body-multiple-params.md b/docs/em/docs/tutorial/body-multiple-params.md
new file mode 100644
index 000000000..9ada7dee1
--- /dev/null
+++ b/docs/em/docs/tutorial/body-multiple-params.md
@@ -0,0 +1,213 @@
+# 💪 - 💗 🔢
+
+🔜 👈 👥 ✔️ 👀 ❔ ⚙️ `Path` & `Query`, ➡️ 👀 🌅 🏧 ⚙️ 📨 💪 📄.
+
+## 🌀 `Path`, `Query` & 💪 🔢
+
+🥇, ↗️, 👆 💪 🌀 `Path`, `Query` & 📨 💪 🔢 📄 ➡ & **FastAPI** 🔜 💭 ⚫️❔.
+
+& 👆 💪 📣 💪 🔢 📦, ⚒ 🔢 `None`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="19-21"
+ {!> ../../../docs_src/body_multiple_params/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="17-19"
+ {!> ../../../docs_src/body_multiple_params/tutorial001_py310.py!}
+ ```
+
+!!! note
+ 👀 👈, 👉 💼, `item` 👈 🔜 ✊ ⚪️➡️ 💪 📦. ⚫️ ✔️ `None` 🔢 💲.
+
+## 💗 💪 🔢
+
+⏮️ 🖼, *➡ 🛠️* 🔜 ⌛ 🎻 💪 ⏮️ 🔢 `Item`, 💖:
+
+```JSON
+{
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2
+}
+```
+
+✋️ 👆 💪 📣 💗 💪 🔢, ✅ `item` & `user`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/body_multiple_params/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_multiple_params/tutorial002_py310.py!}
+ ```
+
+👉 💼, **FastAPI** 🔜 👀 👈 📤 🌅 🌘 1️⃣ 💪 🔢 🔢 (2️⃣ 🔢 👈 Pydantic 🏷).
+
+, ⚫️ 🔜 ⤴️ ⚙️ 🔢 📛 🔑 (🏑 📛) 💪, & ⌛ 💪 💖:
+
+```JSON
+{
+ "item": {
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2
+ },
+ "user": {
+ "username": "dave",
+ "full_name": "Dave Grohl"
+ }
+}
+```
+
+!!! note
+ 👀 👈 ✋️ `item` 📣 🎏 🌌 ⏭, ⚫️ 🔜 ⌛ 🔘 💪 ⏮️ 🔑 `item`.
+
+
+**FastAPI** 🔜 🏧 🛠️ ⚪️➡️ 📨, 👈 🔢 `item` 📨 ⚫️ 🎯 🎚 & 🎏 `user`.
+
+⚫️ 🔜 🎭 🔬 ⚗ 💽, & 🔜 📄 ⚫️ 💖 👈 🗄 🔗 & 🏧 🩺.
+
+## ⭐ 💲 💪
+
+🎏 🌌 📤 `Query` & `Path` 🔬 ➕ 💽 🔢 & ➡ 🔢, **FastAPI** 🚚 🌓 `Body`.
+
+🖼, ↔ ⏮️ 🏷, 👆 💪 💭 👈 👆 💚 ✔️ ➕1️⃣ 🔑 `importance` 🎏 💪, 🥈 `item` & `user`.
+
+🚥 👆 📣 ⚫️, ↩️ ⚫️ ⭐ 💲, **FastAPI** 🔜 🤔 👈 ⚫️ 🔢 🔢.
+
+✋️ 👆 💪 💡 **FastAPI** 😥 ⚫️ ➕1️⃣ 💪 🔑 ⚙️ `Body`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/body_multiple_params/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!}
+ ```
+
+👉 💼, **FastAPI** 🔜 ⌛ 💪 💖:
+
+```JSON
+{
+ "item": {
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2
+ },
+ "user": {
+ "username": "dave",
+ "full_name": "Dave Grohl"
+ },
+ "importance": 5
+}
+```
+
+🔄, ⚫️ 🔜 🗜 📊 🆎, ✔, 📄, ♒️.
+
+## 💗 💪 = & 🔢
+
+↗️, 👆 💪 📣 🌖 🔢 🔢 🕐❔ 👆 💪, 🌖 🙆 💪 🔢.
+
+, 🔢, ⭐ 💲 🔬 🔢 🔢, 👆 🚫 ✔️ 🎯 🚮 `Query`, 👆 💪:
+
+```Python
+q: Union[str, None] = None
+```
+
+⚖️ 🐍 3️⃣.1️⃣0️⃣ & 🔛:
+
+```Python
+q: str | None = None
+```
+
+🖼:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="27"
+ {!> ../../../docs_src/body_multiple_params/tutorial004.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="26"
+ {!> ../../../docs_src/body_multiple_params/tutorial004_py310.py!}
+ ```
+
+!!! info
+ `Body` ✔️ 🌐 🎏 ➕ 🔬 & 🗃 🔢 `Query`,`Path` & 🎏 👆 🔜 👀 ⏪.
+
+## ⏯ 👁 💪 🔢
+
+➡️ 💬 👆 🕴 ✔️ 👁 `item` 💪 🔢 ⚪️➡️ Pydantic 🏷 `Item`.
+
+🔢, **FastAPI** 🔜 ⤴️ ⌛ 🚮 💪 🔗.
+
+✋️ 🚥 👆 💚 ⚫️ ⌛ 🎻 ⏮️ 🔑 `item` & 🔘 ⚫️ 🏷 🎚, ⚫️ 🔨 🕐❔ 👆 📣 ➕ 💪 🔢, 👆 💪 ⚙️ 🎁 `Body` 🔢 `embed`:
+
+```Python
+item: Item = Body(embed=True)
+```
+
+:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/body_multiple_params/tutorial005.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="15"
+ {!> ../../../docs_src/body_multiple_params/tutorial005_py310.py!}
+ ```
+
+👉 💼 **FastAPI** 🔜 ⌛ 💪 💖:
+
+```JSON hl_lines="2"
+{
+ "item": {
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2
+ }
+}
+```
+
+↩️:
+
+```JSON
+{
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2
+}
+```
+
+## 🌃
+
+👆 💪 🚮 💗 💪 🔢 👆 *➡ 🛠️ 🔢*, ✋️ 📨 💪 🕴 ✔️ 👁 💪.
+
+✋️ **FastAPI** 🔜 🍵 ⚫️, 🤝 👆 ☑ 📊 👆 🔢, & ✔ & 📄 ☑ 🔗 *➡ 🛠️*.
+
+👆 💪 📣 ⭐ 💲 📨 🍕 💪.
+
+& 👆 💪 💡 **FastAPI** ⏯ 💪 🔑 🕐❔ 📤 🕴 👁 🔢 📣.
diff --git a/docs/em/docs/tutorial/body-nested-models.md b/docs/em/docs/tutorial/body-nested-models.md
new file mode 100644
index 000000000..f4bd50f5c
--- /dev/null
+++ b/docs/em/docs/tutorial/body-nested-models.md
@@ -0,0 +1,382 @@
+# 💪 - 🔁 🏷
+
+⏮️ **FastAPI**, 👆 💪 🔬, ✔, 📄, & ⚙️ 🎲 🙇 🐦 🏷 (👏 Pydantic).
+
+## 📇 🏑
+
+👆 💪 🔬 🔢 🏾. 🖼, 🐍 `list`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/body_nested_models/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/body_nested_models/tutorial001_py310.py!}
+ ```
+
+👉 🔜 ⚒ `tags` 📇, 👐 ⚫️ 🚫 📣 🆎 🔣 📇.
+
+## 📇 🏑 ⏮️ 🆎 🔢
+
+✋️ 🐍 ✔️ 🎯 🌌 📣 📇 ⏮️ 🔗 🆎, ⚖️ "🆎 🔢":
+
+### 🗄 ⌨ `List`
+
+🐍 3️⃣.9️⃣ & 🔛 👆 💪 ⚙️ 🐩 `list` 📣 👫 🆎 ✍ 👥 🔜 👀 🔛. 👶
+
+✋️ 🐍 ⏬ ⏭ 3️⃣.9️⃣ (3️⃣.6️⃣ & 🔛), 👆 🥇 💪 🗄 `List` ⚪️➡️ 🐩 🐍 `typing` 🕹:
+
+```Python hl_lines="1"
+{!> ../../../docs_src/body_nested_models/tutorial002.py!}
+```
+
+### 📣 `list` ⏮️ 🆎 🔢
+
+📣 🆎 👈 ✔️ 🆎 🔢 (🔗 🆎), 💖 `list`, `dict`, `tuple`:
+
+* 🚥 👆 🐍 ⏬ 🔅 🌘 3️⃣.9️⃣, 🗄 👫 🌓 ⏬ ⚪️➡️ `typing` 🕹
+* 🚶♀️ 🔗 🆎(Ⓜ) "🆎 🔢" ⚙️ ⬜ 🗜: `[` & `]`
+
+🐍 3️⃣.9️⃣ ⚫️ 🔜:
+
+```Python
+my_list: list[str]
+```
+
+⏬ 🐍 ⏭ 3️⃣.9️⃣, ⚫️ 🔜:
+
+```Python
+from typing import List
+
+my_list: List[str]
+```
+
+👈 🌐 🐩 🐍 ❕ 🆎 📄.
+
+⚙️ 👈 🎏 🐩 ❕ 🏷 🔢 ⏮️ 🔗 🆎.
+
+, 👆 🖼, 👥 💪 ⚒ `tags` 🎯 "📇 🎻":
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/body_nested_models/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/body_nested_models/tutorial002_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/body_nested_models/tutorial002_py310.py!}
+ ```
+
+## ⚒ 🆎
+
+✋️ ⤴️ 👥 💭 🔃 ⚫️, & 🤔 👈 🔖 🚫🔜 🚫 🔁, 👫 🔜 🎲 😍 🎻.
+
+& 🐍 ✔️ 🎁 💽 🆎 ⚒ 😍 🏬, `set`.
+
+⤴️ 👥 💪 📣 `tags` ⚒ 🎻:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="1 14"
+ {!> ../../../docs_src/body_nested_models/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/body_nested_models/tutorial003_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/body_nested_models/tutorial003_py310.py!}
+ ```
+
+⏮️ 👉, 🚥 👆 📨 📨 ⏮️ ❎ 📊, ⚫️ 🔜 🗜 ⚒ 😍 🏬.
+
+& 🕐❔ 👆 🔢 👈 📊, 🚥 ℹ ✔️ ❎, ⚫️ 🔜 🔢 ⚒ 😍 🏬.
+
+& ⚫️ 🔜 ✍ / 📄 ➡️ 💁♂️.
+
+## 🐦 🏷
+
+🔠 🔢 Pydantic 🏷 ✔️ 🆎.
+
+✋️ 👈 🆎 💪 ⚫️ ➕1️⃣ Pydantic 🏷.
+
+, 👆 💪 📣 🙇 🐦 🎻 "🎚" ⏮️ 🎯 🔢 📛, 🆎 & 🔬.
+
+🌐 👈, 🎲 🐦.
+
+### 🔬 📊
+
+🖼, 👥 💪 🔬 `Image` 🏷:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9-11"
+ {!> ../../../docs_src/body_nested_models/tutorial004.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="9-11"
+ {!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7-9"
+ {!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
+ ```
+
+### ⚙️ 📊 🆎
+
+& ⤴️ 👥 💪 ⚙️ ⚫️ 🆎 🔢:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_nested_models/tutorial004.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
+ ```
+
+👉 🔜 ⛓ 👈 **FastAPI** 🔜 ⌛ 💪 🎏:
+
+```JSON
+{
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2,
+ "tags": ["rock", "metal", "bar"],
+ "image": {
+ "url": "http://example.com/baz.jpg",
+ "name": "The Foo live"
+ }
+}
+```
+
+🔄, 🤸 👈 📄, ⏮️ **FastAPI** 👆 🤚:
+
+* 👨🎨 🐕🦺 (🛠️, ♒️), 🐦 🏷
+* 💽 🛠️
+* 💽 🔬
+* 🏧 🧾
+
+## 🎁 🆎 & 🔬
+
+↖️ ⚪️➡️ 😐 ⭐ 🆎 💖 `str`, `int`, `float`, ♒️. 👆 💪 ⚙️ 🌅 🏗 ⭐ 🆎 👈 😖 ⚪️➡️ `str`.
+
+👀 🌐 🎛 👆 ✔️, 🛒 🩺 Pydantic 😍 🆎. 👆 🔜 👀 🖼 ⏭ 📃.
+
+🖼, `Image` 🏷 👥 ✔️ `url` 🏑, 👥 💪 📣 ⚫️ ↩️ `str`, Pydantic `HttpUrl`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="4 10"
+ {!> ../../../docs_src/body_nested_models/tutorial005.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="4 10"
+ {!> ../../../docs_src/body_nested_models/tutorial005_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="2 8"
+ {!> ../../../docs_src/body_nested_models/tutorial005_py310.py!}
+ ```
+
+🎻 🔜 ✅ ☑ 📛, & 📄 🎻 🔗 / 🗄 ✅.
+
+## 🔢 ⏮️ 📇 📊
+
+👆 💪 ⚙️ Pydantic 🏷 🏾 `list`, `set`, ♒️:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_nested_models/tutorial006.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_nested_models/tutorial006_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body_nested_models/tutorial006_py310.py!}
+ ```
+
+👉 🔜 ⌛ (🗜, ✔, 📄, ♒️) 🎻 💪 💖:
+
+```JSON hl_lines="11"
+{
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2,
+ "tags": [
+ "rock",
+ "metal",
+ "bar"
+ ],
+ "images": [
+ {
+ "url": "http://example.com/baz.jpg",
+ "name": "The Foo live"
+ },
+ {
+ "url": "http://example.com/dave.jpg",
+ "name": "The Baz"
+ }
+ ]
+}
+```
+
+!!! info
+ 👀 ❔ `images` 🔑 🔜 ✔️ 📇 🖼 🎚.
+
+## 🙇 🐦 🏷
+
+👆 💪 🔬 🎲 🙇 🐦 🏷:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9 14 20 23 27"
+ {!> ../../../docs_src/body_nested_models/tutorial007.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="9 14 20 23 27"
+ {!> ../../../docs_src/body_nested_models/tutorial007_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7 12 18 21 25"
+ {!> ../../../docs_src/body_nested_models/tutorial007_py310.py!}
+ ```
+
+!!! info
+ 👀 ❔ `Offer` ✔️ 📇 `Item`Ⓜ, ❔ 🔄 ✔️ 📦 📇 `Image`Ⓜ
+
+## 💪 😁 📇
+
+🚥 🔝 🎚 💲 🎻 💪 👆 ⌛ 🎻 `array` (🐍 `list`), 👆 💪 📣 🆎 🔢 🔢, 🎏 Pydantic 🏷:
+
+```Python
+images: List[Image]
+```
+
+⚖️ 🐍 3️⃣.9️⃣ & 🔛:
+
+```Python
+images: list[Image]
+```
+
+:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="15"
+ {!> ../../../docs_src/body_nested_models/tutorial008.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/body_nested_models/tutorial008_py39.py!}
+ ```
+
+## 👨🎨 🐕🦺 🌐
+
+& 👆 🤚 👨🎨 🐕🦺 🌐.
+
+🏬 🔘 📇:
+
+
+
+👆 🚫 🚫 🤚 👉 😇 👨🎨 🐕🦺 🚥 👆 👷 🔗 ⏮️ `dict` ↩️ Pydantic 🏷.
+
+✋️ 👆 🚫 ✔️ 😟 🔃 👫 👯♂️, 📨 #️⃣ 🗜 🔁 & 👆 🔢 🗜 🔁 🎻 💁♂️.
+
+## 💪 ❌ `dict`Ⓜ
+
+👆 💪 📣 💪 `dict` ⏮️ 🔑 🆎 & 💲 🎏 🆎.
+
+🍵 ✔️ 💭 ⏪ ⚫️❔ ☑ 🏑/🔢 📛 (🔜 💼 ⏮️ Pydantic 🏷).
+
+👉 🔜 ⚠ 🚥 👆 💚 📨 🔑 👈 👆 🚫 ⏪ 💭.
+
+---
+
+🎏 ⚠ 💼 🕐❔ 👆 💚 ✔️ 🔑 🎏 🆎, ✅ `int`.
+
+👈 ⚫️❔ 👥 🔜 👀 📥.
+
+👉 💼, 👆 🔜 🚫 🙆 `dict` 📏 ⚫️ ✔️ `int` 🔑 ⏮️ `float` 💲:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/body_nested_models/tutorial009.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/body_nested_models/tutorial009_py39.py!}
+ ```
+
+!!! tip
+ ✔️ 🤯 👈 🎻 🕴 🐕🦺 `str` 🔑.
+
+ ✋️ Pydantic ✔️ 🏧 💽 🛠️.
+
+ 👉 ⛓ 👈, ✋️ 👆 🛠️ 👩💻 💪 🕴 📨 🎻 🔑, 📏 👈 🎻 🔌 😁 🔢, Pydantic 🔜 🗜 👫 & ✔ 👫.
+
+ & `dict` 👆 📨 `weights` 🔜 🤙 ✔️ `int` 🔑 & `float` 💲.
+
+## 🌃
+
+⏮️ **FastAPI** 👆 ✔️ 🔆 💪 🚚 Pydantic 🏷, ⏪ 🚧 👆 📟 🙅, 📏 & 😍.
+
+✋️ ⏮️ 🌐 💰:
+
+* 👨🎨 🐕🦺 (🛠️ 🌐 ❗)
+* 💽 🛠️ (.Ⓜ.. ✍ / 🛠️)
+* 💽 🔬
+* 🔗 🧾
+* 🏧 🩺
diff --git a/docs/em/docs/tutorial/body-updates.md b/docs/em/docs/tutorial/body-updates.md
new file mode 100644
index 000000000..98058ab52
--- /dev/null
+++ b/docs/em/docs/tutorial/body-updates.md
@@ -0,0 +1,155 @@
+# 💪 - ℹ
+
+## ℹ ❎ ⏮️ `PUT`
+
+ℹ 🏬 👆 💪 ⚙️ 🇺🇸🔍 `PUT` 🛠️.
+
+👆 💪 ⚙️ `jsonable_encoder` 🗜 🔢 💽 📊 👈 💪 🏪 🎻 (✅ ⏮️ ☁ 💽). 🖼, 🏭 `datetime` `str`.
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="30-35"
+ {!> ../../../docs_src/body_updates/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="30-35"
+ {!> ../../../docs_src/body_updates/tutorial001_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="28-33"
+ {!> ../../../docs_src/body_updates/tutorial001_py310.py!}
+ ```
+
+`PUT` ⚙️ 📨 💽 👈 🔜 ❎ ♻ 💽.
+
+### ⚠ 🔃 ❎
+
+👈 ⛓ 👈 🚥 👆 💚 ℹ 🏬 `bar` ⚙️ `PUT` ⏮️ 💪 ⚗:
+
+```Python
+{
+ "name": "Barz",
+ "price": 3,
+ "description": None,
+}
+```
+
+↩️ ⚫️ 🚫 🔌 ⏪ 🏪 🔢 `"tax": 20.2`, 🔢 🏷 🔜 ✊ 🔢 💲 `"tax": 10.5`.
+
+& 📊 🔜 🖊 ⏮️ 👈 "🆕" `tax` `10.5`.
+
+## 🍕 ℹ ⏮️ `PATCH`
+
+👆 💪 ⚙️ 🇺🇸🔍 `PATCH` 🛠️ *🍕* ℹ 💽.
+
+👉 ⛓ 👈 👆 💪 📨 🕴 💽 👈 👆 💚 ℹ, 🍂 🎂 🐣.
+
+!!! Note
+ `PATCH` 🌘 🛎 ⚙️ & 💭 🌘 `PUT`.
+
+ & 📚 🏉 ⚙️ 🕴 `PUT`, 🍕 ℹ.
+
+ 👆 **🆓** ⚙️ 👫 👐 👆 💚, **FastAPI** 🚫 🚫 🙆 🚫.
+
+ ✋️ 👉 🦮 🎦 👆, 🌖 ⚖️ 🌘, ❔ 👫 🎯 ⚙️.
+
+### ⚙️ Pydantic `exclude_unset` 🔢
+
+🚥 👆 💚 📨 🍕 ℹ, ⚫️ 📶 ⚠ ⚙️ 🔢 `exclude_unset` Pydantic 🏷 `.dict()`.
+
+💖 `item.dict(exclude_unset=True)`.
+
+👈 🔜 🏗 `dict` ⏮️ 🕴 💽 👈 ⚒ 🕐❔ 🏗 `item` 🏷, 🚫 🔢 💲.
+
+⤴️ 👆 💪 ⚙️ 👉 🏗 `dict` ⏮️ 🕴 💽 👈 ⚒ (📨 📨), 🚫 🔢 💲:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="34"
+ {!> ../../../docs_src/body_updates/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="34"
+ {!> ../../../docs_src/body_updates/tutorial002_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="32"
+ {!> ../../../docs_src/body_updates/tutorial002_py310.py!}
+ ```
+
+### ⚙️ Pydantic `update` 🔢
+
+🔜, 👆 💪 ✍ 📁 ♻ 🏷 ⚙️ `.copy()`, & 🚶♀️ `update` 🔢 ⏮️ `dict` ⚗ 💽 ℹ.
+
+💖 `stored_item_model.copy(update=update_data)`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="35"
+ {!> ../../../docs_src/body_updates/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="35"
+ {!> ../../../docs_src/body_updates/tutorial002_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="33"
+ {!> ../../../docs_src/body_updates/tutorial002_py310.py!}
+ ```
+
+### 🍕 ℹ 🌃
+
+📄, ✔ 🍕 ℹ 👆 🔜:
+
+* (⚗) ⚙️ `PATCH` ↩️ `PUT`.
+* 🗃 🏪 💽.
+* 🚮 👈 💽 Pydantic 🏷.
+* 🏗 `dict` 🍵 🔢 💲 ⚪️➡️ 🔢 🏷 (⚙️ `exclude_unset`).
+ * 👉 🌌 👆 💪 ℹ 🕴 💲 🤙 ⚒ 👩💻, ↩️ 🔐 💲 ⏪ 🏪 ⏮️ 🔢 💲 👆 🏷.
+* ✍ 📁 🏪 🏷, 🛠️ ⚫️ 🔢 ⏮️ 📨 🍕 ℹ (⚙️ `update` 🔢).
+* 🗜 📁 🏷 🕳 👈 💪 🏪 👆 💽 (🖼, ⚙️ `jsonable_encoder`).
+ * 👉 ⭐ ⚙️ 🏷 `.dict()` 👩🔬 🔄, ✋️ ⚫️ ⚒ 💭 (& 🗜) 💲 💽 🆎 👈 💪 🗜 🎻, 🖼, `datetime` `str`.
+* 🖊 💽 👆 💽.
+* 📨 ℹ 🏷.
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="30-37"
+ {!> ../../../docs_src/body_updates/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="30-37"
+ {!> ../../../docs_src/body_updates/tutorial002_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="28-35"
+ {!> ../../../docs_src/body_updates/tutorial002_py310.py!}
+ ```
+
+!!! tip
+ 👆 💪 🤙 ⚙️ 👉 🎏 ⚒ ⏮️ 🇺🇸🔍 `PUT` 🛠️.
+
+ ✋️ 🖼 📥 ⚙️ `PATCH` ↩️ ⚫️ ✍ 👫 ⚙️ 💼.
+
+!!! note
+ 👀 👈 🔢 🏷 ✔.
+
+ , 🚥 👆 💚 📨 🍕 ℹ 👈 💪 🚫 🌐 🔢, 👆 💪 ✔️ 🏷 ⏮️ 🌐 🔢 ™ 📦 (⏮️ 🔢 💲 ⚖️ `None`).
+
+ 🔬 ⚪️➡️ 🏷 ⏮️ 🌐 📦 💲 **ℹ** & 🏷 ⏮️ ✔ 💲 **🏗**, 👆 💪 ⚙️ 💭 🔬 [➕ 🏷](extra-models.md){.internal-link target=_blank}.
diff --git a/docs/em/docs/tutorial/body.md b/docs/em/docs/tutorial/body.md
new file mode 100644
index 000000000..ca2f113bf
--- /dev/null
+++ b/docs/em/docs/tutorial/body.md
@@ -0,0 +1,213 @@
+# 📨 💪
+
+🕐❔ 👆 💪 📨 📊 ⚪️➡️ 👩💻 (➡️ 💬, 🖥) 👆 🛠️, 👆 📨 ⚫️ **📨 💪**.
+
+**📨** 💪 📊 📨 👩💻 👆 🛠️. **📨** 💪 💽 👆 🛠️ 📨 👩💻.
+
+👆 🛠️ 🌖 🕧 ✔️ 📨 **📨** 💪. ✋️ 👩💻 🚫 🎯 💪 📨 **📨** 💪 🌐 🕰.
+
+📣 **📨** 💪, 👆 ⚙️ Pydantic 🏷 ⏮️ 🌐 👫 🏋️ & 💰.
+
+!!! info
+ 📨 💽, 👆 🔜 ⚙️ 1️⃣: `POST` (🌅 ⚠), `PUT`, `DELETE` ⚖️ `PATCH`.
+
+ 📨 💪 ⏮️ `GET` 📨 ✔️ ⚠ 🎭 🔧, 👐, ⚫️ 🐕🦺 FastAPI, 🕴 📶 🏗/😕 ⚙️ 💼.
+
+ ⚫️ 🚫, 🎓 🩺 ⏮️ 🦁 🎚 🏆 🚫 🎦 🧾 💪 🕐❔ ⚙️ `GET`, & 🗳 🖕 💪 🚫 🐕🦺 ⚫️.
+
+## 🗄 Pydantic `BaseModel`
+
+🥇, 👆 💪 🗄 `BaseModel` ⚪️➡️ `pydantic`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="2"
+ {!> ../../../docs_src/body/tutorial001_py310.py!}
+ ```
+
+## ✍ 👆 💽 🏷
+
+⤴️ 👆 📣 👆 💽 🏷 🎓 👈 😖 ⚪️➡️ `BaseModel`.
+
+⚙️ 🐩 🐍 🆎 🌐 🔢:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="7-11"
+ {!> ../../../docs_src/body/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="5-9"
+ {!> ../../../docs_src/body/tutorial001_py310.py!}
+ ```
+
+🎏 🕐❔ 📣 🔢 🔢, 🕐❔ 🏷 🔢 ✔️ 🔢 💲, ⚫️ 🚫 ✔. ⏪, ⚫️ ✔. ⚙️ `None` ⚒ ⚫️ 📦.
+
+🖼, 👉 🏷 🔛 📣 🎻 "`object`" (⚖️ 🐍 `dict`) 💖:
+
+```JSON
+{
+ "name": "Foo",
+ "description": "An optional description",
+ "price": 45.2,
+ "tax": 3.5
+}
+```
+
+... `description` & `tax` 📦 (⏮️ 🔢 💲 `None`), 👉 🎻 "`object`" 🔜 ☑:
+
+```JSON
+{
+ "name": "Foo",
+ "price": 45.2
+}
+```
+
+## 📣 ⚫️ 🔢
+
+🚮 ⚫️ 👆 *➡ 🛠️*, 📣 ⚫️ 🎏 🌌 👆 📣 ➡ & 🔢 🔢:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="16"
+ {!> ../../../docs_src/body/tutorial001_py310.py!}
+ ```
+
+...& 📣 🚮 🆎 🏷 👆 ✍, `Item`.
+
+## 🏁
+
+⏮️ 👈 🐍 🆎 📄, **FastAPI** 🔜:
+
+* ✍ 💪 📨 🎻.
+* 🗜 🔗 🆎 (🚥 💪).
+* ✔ 💽.
+ * 🚥 💽 ❌, ⚫️ 🔜 📨 👌 & 🆑 ❌, ☠️ ⚫️❔ 🌐❔ & ⚫️❔ ❌ 📊.
+* 🤝 👆 📨 📊 🔢 `item`.
+ * 👆 📣 ⚫️ 🔢 🆎 `Item`, 👆 🔜 ✔️ 🌐 👨🎨 🐕🦺 (🛠️, ♒️) 🌐 🔢 & 👫 🆎.
+* 🏗 🎻 🔗 🔑 👆 🏷, 👆 💪 ⚙️ 👫 🙆 🙆 👆 💖 🚥 ⚫️ ⚒ 🔑 👆 🏗.
+* 👈 🔗 🔜 🍕 🏗 🗄 🔗, & ⚙️ 🏧 🧾 ⚜.
+
+## 🏧 🩺
+
+🎻 🔗 👆 🏷 🔜 🍕 👆 🗄 🏗 🔗, & 🔜 🎦 🎓 🛠️ 🩺:
+
+
+
+& 🔜 ⚙️ 🛠️ 🩺 🔘 🔠 *➡ 🛠️* 👈 💪 👫:
+
+
+
+## 👨🎨 🐕🦺
+
+👆 👨🎨, 🔘 👆 🔢 👆 🔜 🤚 🆎 🔑 & 🛠️ 🌐 (👉 🚫🔜 🔨 🚥 👆 📨 `dict` ↩️ Pydantic 🏷):
+
+
+
+👆 🤚 ❌ ✅ ❌ 🆎 🛠️:
+
+
+
+👉 🚫 🤞, 🎂 🛠️ 🏗 🤭 👈 🔧.
+
+& ⚫️ 🙇 💯 🔧 🌓, ⏭ 🙆 🛠️, 🚚 ⚫️ 🔜 👷 ⏮️ 🌐 👨🎨.
+
+📤 🔀 Pydantic ⚫️ 🐕🦺 👉.
+
+⏮️ 🖼 ✊ ⏮️ 🎙 🎙 📟.
+
+✋️ 👆 🔜 🤚 🎏 👨🎨 🐕🦺 ⏮️ 🗒 & 🌅 🎏 🐍 👨🎨:
+
+
+
+!!! tip
+ 🚥 👆 ⚙️ 🗒 👆 👨🎨, 👆 💪 ⚙️ Pydantic 🗒 📁.
+
+ ⚫️ 📉 👨🎨 🐕🦺 Pydantic 🏷, ⏮️:
+
+ * 🚘-🛠️
+ * 🆎 ✅
+ * 🛠️
+ * 🔎
+ * 🔬
+
+## ⚙️ 🏷
+
+🔘 🔢, 👆 💪 🔐 🌐 🔢 🏷 🎚 🔗:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="21"
+ {!> ../../../docs_src/body/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/body/tutorial002_py310.py!}
+ ```
+
+## 📨 💪 ➕ ➡ 🔢
+
+👆 💪 📣 ➡ 🔢 & 📨 💪 🎏 🕰.
+
+**FastAPI** 🔜 🤔 👈 🔢 🔢 👈 🏏 ➡ 🔢 🔜 **✊ ⚪️➡️ ➡**, & 👈 🔢 🔢 👈 📣 Pydantic 🏷 🔜 **✊ ⚪️➡️ 📨 💪**.
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="17-18"
+ {!> ../../../docs_src/body/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="15-16"
+ {!> ../../../docs_src/body/tutorial003_py310.py!}
+ ```
+
+## 📨 💪 ➕ ➡ ➕ 🔢 🔢
+
+👆 💪 📣 **💪**, **➡** & **🔢** 🔢, 🌐 🎏 🕰.
+
+**FastAPI** 🔜 🤔 🔠 👫 & ✊ 📊 ⚪️➡️ ☑ 🥉.
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body/tutorial004.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="16"
+ {!> ../../../docs_src/body/tutorial004_py310.py!}
+ ```
+
+🔢 🔢 🔜 🤔 ⏩:
+
+* 🚥 🔢 📣 **➡**, ⚫️ 🔜 ⚙️ ➡ 🔢.
+* 🚥 🔢 **⭐ 🆎** (💖 `int`, `float`, `str`, `bool`, ♒️) ⚫️ 🔜 🔬 **🔢** 🔢.
+* 🚥 🔢 📣 🆎 **Pydantic 🏷**, ⚫️ 🔜 🔬 📨 **💪**.
+
+!!! note
+ FastAPI 🔜 💭 👈 💲 `q` 🚫 ✔ ↩️ 🔢 💲 `= None`.
+
+ `Union` `Union[str, None]` 🚫 ⚙️ FastAPI, ✋️ 🔜 ✔ 👆 👨🎨 🤝 👆 👍 🐕🦺 & 🔍 ❌.
+
+## 🍵 Pydantic
+
+🚥 👆 🚫 💚 ⚙️ Pydantic 🏷, 👆 💪 ⚙️ **💪** 🔢. 👀 🩺 [💪 - 💗 🔢: ⭐ 💲 💪](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.
diff --git a/docs/em/docs/tutorial/cookie-params.md b/docs/em/docs/tutorial/cookie-params.md
new file mode 100644
index 000000000..47f4a62f5
--- /dev/null
+++ b/docs/em/docs/tutorial/cookie-params.md
@@ -0,0 +1,49 @@
+# 🍪 🔢
+
+👆 💪 🔬 🍪 🔢 🎏 🌌 👆 🔬 `Query` & `Path` 🔢.
+
+## 🗄 `Cookie`
+
+🥇 🗄 `Cookie`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/cookie_params/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
+ ```
+
+## 📣 `Cookie` 🔢
+
+⤴️ 📣 🍪 🔢 ⚙️ 🎏 📊 ⏮️ `Path` & `Query`.
+
+🥇 💲 🔢 💲, 👆 💪 🚶♀️ 🌐 ➕ 🔬 ⚖️ ✍ 🔢:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/cookie_params/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
+ ```
+
+!!! note "📡 ℹ"
+ `Cookie` "👭" 🎓 `Path` & `Query`. ⚫️ 😖 ⚪️➡️ 🎏 ⚠ `Param` 🎓.
+
+ ✋️ 💭 👈 🕐❔ 👆 🗄 `Query`, `Path`, `Cookie` & 🎏 ⚪️➡️ `fastapi`, 👈 🤙 🔢 👈 📨 🎁 🎓.
+
+!!! info
+ 📣 🍪, 👆 💪 ⚙️ `Cookie`, ↩️ ⏪ 🔢 🔜 🔬 🔢 🔢.
+
+## 🌃
+
+📣 🍪 ⏮️ `Cookie`, ⚙️ 🎏 ⚠ ⚓ `Query` & `Path`.
diff --git a/docs/em/docs/tutorial/cors.md b/docs/em/docs/tutorial/cors.md
new file mode 100644
index 000000000..8c5e33ed7
--- /dev/null
+++ b/docs/em/docs/tutorial/cors.md
@@ -0,0 +1,84 @@
+# ⚜ (✖️-🇨🇳 ℹ 🤝)
+
+⚜ ⚖️ "✖️-🇨🇳 ℹ 🤝" 🔗 ⚠ 🕐❔ 🕸 🏃♂ 🖥 ✔️ 🕸 📟 👈 🔗 ⏮️ 👩💻, & 👩💻 🎏 "🇨🇳" 🌘 🕸.
+
+## 🇨🇳
+
+🇨🇳 🌀 🛠️ (`http`, `https`), 🆔 (`myapp.com`, `localhost`, `localhost.tiangolo.com`), & ⛴ (`80`, `443`, `8080`).
+
+, 🌐 👫 🎏 🇨🇳:
+
+* `http://localhost`
+* `https://localhost`
+* `http://localhost:8080`
+
+🚥 👫 🌐 `localhost`, 👫 ⚙️ 🎏 🛠️ ⚖️ ⛴,, 👫 🎏 "🇨🇳".
+
+## 🔁
+
+, ➡️ 💬 👆 ✔️ 🕸 🏃 👆 🖥 `http://localhost:8080`, & 🚮 🕸 🔄 🔗 ⏮️ 👩💻 🏃 `http://localhost` (↩️ 👥 🚫 ✔ ⛴, 🖥 🔜 🤔 🔢 ⛴ `80`).
+
+⤴️, 🖥 🔜 📨 🇺🇸🔍 `OPTIONS` 📨 👩💻, & 🚥 👩💻 📨 ☑ 🎚 ✔ 📻 ⚪️➡️ 👉 🎏 🇨🇳 (`http://localhost:8080`) ⤴️ 🖥 🔜 ➡️ 🕸 🕸 📨 🚮 📨 👩💻.
+
+🏆 👉, 👩💻 🔜 ✔️ 📇 "✔ 🇨🇳".
+
+👉 💼, ⚫️ 🔜 ✔️ 🔌 `http://localhost:8080` 🕸 👷 ☑.
+
+## 🃏
+
+⚫️ 💪 📣 📇 `"*"` ("🃏") 💬 👈 🌐 ✔.
+
+✋️ 👈 🔜 🕴 ✔ 🎯 🆎 📻, 🚫 🌐 👈 🔌 🎓: 🍪, ✔ 🎚 💖 📚 ⚙️ ⏮️ 📨 🤝, ♒️.
+
+, 🌐 👷 ☑, ⚫️ 👻 ✔ 🎯 ✔ 🇨🇳.
+
+## ⚙️ `CORSMiddleware`
+
+👆 💪 🔗 ⚫️ 👆 **FastAPI** 🈸 ⚙️ `CORSMiddleware`.
+
+* 🗄 `CORSMiddleware`.
+* ✍ 📇 ✔ 🇨🇳 (🎻).
+* 🚮 ⚫️ "🛠️" 👆 **FastAPI** 🈸.
+
+👆 💪 ✔ 🚥 👆 👩💻 ✔:
+
+* 🎓 (✔ 🎚, 🍪, ♒️).
+* 🎯 🇺🇸🔍 👩🔬 (`POST`, `PUT`) ⚖️ 🌐 👫 ⏮️ 🃏 `"*"`.
+* 🎯 🇺🇸🔍 🎚 ⚖️ 🌐 👫 ⏮️ 🃏 `"*"`.
+
+```Python hl_lines="2 6-11 13-19"
+{!../../../docs_src/cors/tutorial001.py!}
+```
+
+🔢 🔢 ⚙️ `CORSMiddleware` 🛠️ 🚫 🔢, 👆 🔜 💪 🎯 🛠️ 🎯 🇨🇳, 👩🔬, ⚖️ 🎚, ✔ 🖥 ✔ ⚙️ 👫 ✖️-🆔 🔑.
+
+📄 ❌ 🐕🦺:
+
+* `allow_origins` - 📇 🇨🇳 👈 🔜 ✔ ⚒ ✖️-🇨🇳 📨. 🤶 Ⓜ. `['https://example.org', 'https://www.example.org']`. 👆 💪 ⚙️ `['*']` ✔ 🙆 🇨🇳.
+* `allow_origin_regex` - 🎻 🎻 🏏 🛡 🇨🇳 👈 🔜 ✔ ⚒ ✖️-🇨🇳 📨. ✅ `'https://.*\.example\.org'`.
+* `allow_methods` - 📇 🇺🇸🔍 👩🔬 👈 🔜 ✔ ✖️-🇨🇳 📨. 🔢 `['GET']`. 👆 💪 ⚙️ `['*']` ✔ 🌐 🐩 👩🔬.
+* `allow_headers` - 📇 🇺🇸🔍 📨 🎚 👈 🔜 🐕🦺 ✖️-🇨🇳 📨. 🔢 `[]`. 👆 💪 ⚙️ `['*']` ✔ 🌐 🎚. `Accept`, `Accept-Language`, `Content-Language` & `Content-Type` 🎚 🕧 ✔ 🙅 ⚜ 📨.
+* `allow_credentials` - 🎦 👈 🍪 🔜 🐕🦺 ✖️-🇨🇳 📨. 🔢 `False`. , `allow_origins` 🚫🔜 ⚒ `['*']` 🎓 ✔, 🇨🇳 🔜 ✔.
+* `expose_headers` - 🎦 🙆 📨 🎚 👈 🔜 ⚒ ♿ 🖥. 🔢 `[]`.
+* `max_age` - ⚒ 🔆 🕰 🥈 🖥 💾 ⚜ 📨. 🔢 `600`.
+
+🛠️ 📨 2️⃣ 🎯 🆎 🇺🇸🔍 📨...
+
+### ⚜ 🛫 📨
+
+👉 🙆 `OPTIONS` 📨 ⏮️ `Origin` & `Access-Control-Request-Method` 🎚.
+
+👉 💼 🛠️ 🔜 🆘 📨 📨 & 📨 ⏮️ ☑ ⚜ 🎚, & 👯♂️ `200` ⚖️ `400` 📨 🎓 🎯.
+
+### 🙅 📨
+
+🙆 📨 ⏮️ `Origin` 🎚. 👉 💼 🛠️ 🔜 🚶♀️ 📨 🔘 😐, ✋️ 🔜 🔌 ☑ ⚜ 🎚 🔛 📨.
+
+## 🌅 ℹ
+
+🌖 ℹ 🔃 ⚜, ✅ 🦎 ⚜ 🧾.
+
+!!! note "📡 ℹ"
+ 👆 💪 ⚙️ `from starlette.middleware.cors import CORSMiddleware`.
+
+ **FastAPI** 🚚 📚 🛠️ `fastapi.middleware` 🏪 👆, 👩💻. ✋️ 🌅 💪 🛠️ 👟 🔗 ⚪️➡️ 💃.
diff --git a/docs/em/docs/tutorial/debugging.md b/docs/em/docs/tutorial/debugging.md
new file mode 100644
index 000000000..c7c11b5ce
--- /dev/null
+++ b/docs/em/docs/tutorial/debugging.md
@@ -0,0 +1,112 @@
+# 🛠️
+
+👆 💪 🔗 🕹 👆 👨🎨, 🖼 ⏮️ 🎙 🎙 📟 ⚖️ 🗒.
+
+## 🤙 `uvicorn`
+
+👆 FastAPI 🈸, 🗄 & 🏃 `uvicorn` 🔗:
+
+```Python hl_lines="1 15"
+{!../../../docs_src/debugging/tutorial001.py!}
+```
+
+### 🔃 `__name__ == "__main__"`
+
+👑 🎯 `__name__ == "__main__"` ✔️ 📟 👈 🛠️ 🕐❔ 👆 📁 🤙 ⏮️:
+
+
+
+---
+
+🚥 👆 ⚙️ 🗒, 👆 💪:
+
+* 📂 "🏃" 🍣.
+* 🖊 🎛 "ℹ...".
+* ⤴️ 🔑 🍣 🎦 🆙.
+* 🖊 📁 ℹ (👉 💼, `main.py`).
+
+⚫️ 🔜 ⤴️ ▶️ 💽 ⏮️ 👆 **FastAPI** 📟, ⛔️ 👆 0️⃣, ♒️.
+
+📥 ❔ ⚫️ 💪 👀:
+
+
diff --git a/docs/em/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/em/docs/tutorial/dependencies/classes-as-dependencies.md
new file mode 100644
index 000000000..e2d2686d3
--- /dev/null
+++ b/docs/em/docs/tutorial/dependencies/classes-as-dependencies.md
@@ -0,0 +1,247 @@
+# 🎓 🔗
+
+⏭ 🤿 ⏬ 🔘 **🔗 💉** ⚙️, ➡️ ♻ ⏮️ 🖼.
+
+## `dict` ⚪️➡️ ⏮️ 🖼
+
+⏮️ 🖼, 👥 🛬 `dict` ⚪️➡️ 👆 🔗 ("☑"):
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/dependencies/tutorial001_py310.py!}
+ ```
+
+✋️ ⤴️ 👥 🤚 `dict` 🔢 `commons` *➡ 🛠️ 🔢*.
+
+& 👥 💭 👈 👨🎨 💪 🚫 🚚 📚 🐕🦺 (💖 🛠️) `dict`Ⓜ, ↩️ 👫 💪 🚫 💭 👫 🔑 & 💲 🆎.
+
+👥 💪 👍...
+
+## ⚫️❔ ⚒ 🔗
+
+🆙 🔜 👆 ✔️ 👀 🔗 📣 🔢.
+
+✋️ 👈 🚫 🕴 🌌 📣 🔗 (👐 ⚫️ 🔜 🎲 🌖 ⚠).
+
+🔑 ⚖ 👈 🔗 🔜 "🇧🇲".
+
+"**🇧🇲**" 🐍 🕳 👈 🐍 💪 "🤙" 💖 🔢.
+
+, 🚥 👆 ✔️ 🎚 `something` (👈 💪 _🚫_ 🔢) & 👆 💪 "🤙" ⚫️ (🛠️ ⚫️) 💖:
+
+```Python
+something()
+```
+
+⚖️
+
+```Python
+something(some_argument, some_keyword_argument="foo")
+```
+
+⤴️ ⚫️ "🇧🇲".
+
+## 🎓 🔗
+
+👆 5️⃣📆 👀 👈 ✍ 👐 🐍 🎓, 👆 ⚙️ 👈 🎏 ❕.
+
+🖼:
+
+```Python
+class Cat:
+ def __init__(self, name: str):
+ self.name = name
+
+
+fluffy = Cat(name="Mr Fluffy")
+```
+
+👉 💼, `fluffy` 👐 🎓 `Cat`.
+
+& ✍ `fluffy`, 👆 "🤙" `Cat`.
+
+, 🐍 🎓 **🇧🇲**.
+
+⤴️, **FastAPI**, 👆 💪 ⚙️ 🐍 🎓 🔗.
+
+⚫️❔ FastAPI 🤙 ✅ 👈 ⚫️ "🇧🇲" (🔢, 🎓 ⚖️ 🕳 🙆) & 🔢 🔬.
+
+🚥 👆 🚶♀️ "🇧🇲" 🔗 **FastAPI**, ⚫️ 🔜 🔬 🔢 👈 "🇧🇲", & 🛠️ 👫 🎏 🌌 🔢 *➡ 🛠️ 🔢*. ✅ 🎧-🔗.
+
+👈 ✔ 🇧🇲 ⏮️ 🙅♂ 🔢 🌐. 🎏 ⚫️ 🔜 *➡ 🛠️ 🔢* ⏮️ 🙅♂ 🔢.
+
+⤴️, 👥 💪 🔀 🔗 "☑" `common_parameters` ⚪️➡️ 🔛 🎓 `CommonQueryParams`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="11-15"
+ {!> ../../../docs_src/dependencies/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="9-13"
+ {!> ../../../docs_src/dependencies/tutorial002_py310.py!}
+ ```
+
+💸 🙋 `__init__` 👩🔬 ⚙️ ✍ 👐 🎓:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/dependencies/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/dependencies/tutorial002_py310.py!}
+ ```
+
+...⚫️ ✔️ 🎏 🔢 👆 ⏮️ `common_parameters`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="6"
+ {!> ../../../docs_src/dependencies/tutorial001_py310.py!}
+ ```
+
+📚 🔢 ⚫️❔ **FastAPI** 🔜 ⚙️ "❎" 🔗.
+
+👯♂️ 💼, ⚫️ 🔜 ✔️:
+
+* 📦 `q` 🔢 🔢 👈 `str`.
+* `skip` 🔢 🔢 👈 `int`, ⏮️ 🔢 `0`.
+* `limit` 🔢 🔢 👈 `int`, ⏮️ 🔢 `100`.
+
+👯♂️ 💼 💽 🔜 🗜, ✔, 📄 🔛 🗄 🔗, ♒️.
+
+## ⚙️ ⚫️
+
+🔜 👆 💪 📣 👆 🔗 ⚙️ 👉 🎓.
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/dependencies/tutorial002_py310.py!}
+ ```
+
+**FastAPI** 🤙 `CommonQueryParams` 🎓. 👉 ✍ "👐" 👈 🎓 & 👐 🔜 🚶♀️ 🔢 `commons` 👆 🔢.
+
+## 🆎 ✍ 🆚 `Depends`
+
+👀 ❔ 👥 ✍ `CommonQueryParams` 🕐 🔛 📟:
+
+```Python
+commons: CommonQueryParams = Depends(CommonQueryParams)
+```
+
+🏁 `CommonQueryParams`,:
+
+```Python
+... = Depends(CommonQueryParams)
+```
+
+...⚫️❔ **FastAPI** 🔜 🤙 ⚙️ 💭 ⚫️❔ 🔗.
+
+⚪️➡️ ⚫️ 👈 FastAPI 🔜 ⚗ 📣 🔢 & 👈 ⚫️❔ FastAPI 🔜 🤙 🤙.
+
+---
+
+👉 💼, 🥇 `CommonQueryParams`,:
+
+```Python
+commons: CommonQueryParams ...
+```
+
+...🚫 ✔️ 🙆 🎁 🔑 **FastAPI**. FastAPI 🏆 🚫 ⚙️ ⚫️ 💽 🛠️, 🔬, ♒️. (⚫️ ⚙️ `= Depends(CommonQueryParams)` 👈).
+
+👆 💪 🤙 ✍:
+
+```Python
+commons = Depends(CommonQueryParams)
+```
+
+...:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/dependencies/tutorial003_py310.py!}
+ ```
+
+✋️ 📣 🆎 💡 👈 🌌 👆 👨🎨 🔜 💭 ⚫️❔ 🔜 🚶♀️ 🔢 `commons`, & ⤴️ ⚫️ 💪 ℹ 👆 ⏮️ 📟 🛠️, 🆎 ✅, ♒️:
+
+
+
+## ⌨
+
+✋️ 👆 👀 👈 👥 ✔️ 📟 🔁 📥, ✍ `CommonQueryParams` 🕐:
+
+```Python
+commons: CommonQueryParams = Depends(CommonQueryParams)
+```
+
+**FastAPI** 🚚 ⌨ 👫 💼, 🌐❔ 🔗 *🎯* 🎓 👈 **FastAPI** 🔜 "🤙" ✍ 👐 🎓 ⚫️.
+
+📚 🎯 💼, 👆 💪 📄:
+
+↩️ ✍:
+
+```Python
+commons: CommonQueryParams = Depends(CommonQueryParams)
+```
+
+...👆 ✍:
+
+```Python
+commons: CommonQueryParams = Depends()
+```
+
+👆 📣 🔗 🆎 🔢, & 👆 ⚙️ `Depends()` 🚮 "🔢" 💲 (👈 ⏮️ `=`) 👈 🔢 🔢, 🍵 🙆 🔢 `Depends()`, ↩️ ✔️ ✍ 🌕 🎓 *🔄* 🔘 `Depends(CommonQueryParams)`.
+
+🎏 🖼 🔜 ⤴️ 👀 💖:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial004.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/dependencies/tutorial004_py310.py!}
+ ```
+
+...& **FastAPI** 🔜 💭 ⚫️❔.
+
+!!! tip
+ 🚥 👈 😑 🌅 😨 🌘 👍, 🤷♂ ⚫️, 👆 🚫 *💪* ⚫️.
+
+ ⚫️ ⌨. ↩️ **FastAPI** 💅 🔃 🤝 👆 📉 📟 🔁.
diff --git a/docs/em/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/em/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md
new file mode 100644
index 000000000..4d54b91c7
--- /dev/null
+++ b/docs/em/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md
@@ -0,0 +1,71 @@
+# 🔗 ➡ 🛠️ 👨🎨
+
+💼 👆 🚫 🤙 💪 📨 💲 🔗 🔘 👆 *➡ 🛠️ 🔢*.
+
+⚖️ 🔗 🚫 📨 💲.
+
+✋️ 👆 💪 ⚫️ 🛠️/❎.
+
+📚 💼, ↩️ 📣 *➡ 🛠️ 🔢* 🔢 ⏮️ `Depends`, 👆 💪 🚮 `list` `dependencies` *➡ 🛠️ 👨🎨*.
+
+## 🚮 `dependencies` *➡ 🛠️ 👨🎨*
+
+*➡ 🛠️ 👨🎨* 📨 📦 ❌ `dependencies`.
+
+⚫️ 🔜 `list` `Depends()`:
+
+```Python hl_lines="17"
+{!../../../docs_src/dependencies/tutorial006.py!}
+```
+
+👉 🔗 🔜 🛠️/❎ 🎏 🌌 😐 🔗. ✋️ 👫 💲 (🚥 👫 📨 🙆) 🏆 🚫 🚶♀️ 👆 *➡ 🛠️ 🔢*.
+
+!!! tip
+ 👨🎨 ✅ ♻ 🔢 🔢, & 🎦 👫 ❌.
+
+ ⚙️ 👉 `dependencies` *➡ 🛠️ 👨🎨* 👆 💪 ⚒ 💭 👫 🛠️ ⏪ ❎ 👨🎨/🏭 ❌.
+
+ ⚫️ 💪 ℹ ❎ 😨 🆕 👩💻 👈 👀 ♻ 🔢 👆 📟 & 💪 💭 ⚫️ 🙃.
+
+!!! info
+ 👉 🖼 👥 ⚙️ 💭 🛃 🎚 `X-Key` & `X-Token`.
+
+ ✋️ 🎰 💼, 🕐❔ 🛠️ 💂♂, 👆 🔜 🤚 🌖 💰 ⚪️➡️ ⚙️ 🛠️ [💂♂ 🚙 (⏭ 📃)](../security/index.md){.internal-link target=_blank}.
+
+## 🔗 ❌ & 📨 💲
+
+👆 💪 ⚙️ 🎏 🔗 *🔢* 👆 ⚙️ 🛎.
+
+### 🔗 📄
+
+👫 💪 📣 📨 📄 (💖 🎚) ⚖️ 🎏 🎧-🔗:
+
+```Python hl_lines="6 11"
+{!../../../docs_src/dependencies/tutorial006.py!}
+```
+
+### 🤚 ⚠
+
+👫 🔗 💪 `raise` ⚠, 🎏 😐 🔗:
+
+```Python hl_lines="8 13"
+{!../../../docs_src/dependencies/tutorial006.py!}
+```
+
+### 📨 💲
+
+& 👫 💪 📨 💲 ⚖️ 🚫, 💲 🏆 🚫 ⚙️.
+
+, 👆 💪 🏤-⚙️ 😐 🔗 (👈 📨 💲) 👆 ⏪ ⚙️ 👱 🙆, & ✋️ 💲 🏆 🚫 ⚙️, 🔗 🔜 🛠️:
+
+```Python hl_lines="9 14"
+{!../../../docs_src/dependencies/tutorial006.py!}
+```
+
+## 🔗 👪 *➡ 🛠️*
+
+⏪, 🕐❔ 👂 🔃 ❔ 📊 🦏 🈸 ([🦏 🈸 - 💗 📁](../../tutorial/bigger-applications.md){.internal-link target=_blank}), 🎲 ⏮️ 💗 📁, 👆 🔜 💡 ❔ 📣 👁 `dependencies` 🔢 👪 *➡ 🛠️*.
+
+## 🌐 🔗
+
+⏭ 👥 🔜 👀 ❔ 🚮 🔗 🎂 `FastAPI` 🈸, 👈 👫 ✔ 🔠 *➡ 🛠️*.
diff --git a/docs/em/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/em/docs/tutorial/dependencies/dependencies-with-yield.md
new file mode 100644
index 000000000..9617667f4
--- /dev/null
+++ b/docs/em/docs/tutorial/dependencies/dependencies-with-yield.md
@@ -0,0 +1,219 @@
+# 🔗 ⏮️ 🌾
+
+FastAPI 🐕🦺 🔗 👈 ➕ 🔁 ⏮️ 🏁.
+
+👉, ⚙️ `yield` ↩️ `return`, & ✍ ➕ 🔁 ⏮️.
+
+!!! tip
+ ⚒ 💭 ⚙️ `yield` 1️⃣ 👁 🕰.
+
+!!! note "📡 ℹ"
+ 🙆 🔢 👈 ☑ ⚙️ ⏮️:
+
+ * `@contextlib.contextmanager` ⚖️
+ * `@contextlib.asynccontextmanager`
+
+ 🔜 ☑ ⚙️ **FastAPI** 🔗.
+
+ 👐, FastAPI ⚙️ 📚 2️⃣ 👨🎨 🔘.
+
+## 💽 🔗 ⏮️ `yield`
+
+🖼, 👆 💪 ⚙️ 👉 ✍ 💽 🎉 & 🔐 ⚫️ ⏮️ 🏁.
+
+🕴 📟 ⏭ & 🔌 `yield` 📄 🛠️ ⏭ 📨 📨:
+
+```Python hl_lines="2-4"
+{!../../../docs_src/dependencies/tutorial007.py!}
+```
+
+🌾 💲 ⚫️❔ 💉 🔘 *➡ 🛠️* & 🎏 🔗:
+
+```Python hl_lines="4"
+{!../../../docs_src/dependencies/tutorial007.py!}
+```
+
+📟 📄 `yield` 📄 🛠️ ⏮️ 📨 ✔️ 🚚:
+
+```Python hl_lines="5-6"
+{!../../../docs_src/dependencies/tutorial007.py!}
+```
+
+!!! tip
+ 👆 💪 ⚙️ `async` ⚖️ 😐 🔢.
+
+ **FastAPI** 🔜 ▶️️ 👜 ⏮️ 🔠, 🎏 ⏮️ 😐 🔗.
+
+## 🔗 ⏮️ `yield` & `try`
+
+🚥 👆 ⚙️ `try` 🍫 🔗 ⏮️ `yield`, 👆 🔜 📨 🙆 ⚠ 👈 🚮 🕐❔ ⚙️ 🔗.
+
+🖼, 🚥 📟 ☝ 🖕, ➕1️⃣ 🔗 ⚖️ *➡ 🛠️*, ⚒ 💽 💵 "💾" ⚖️ ✍ 🙆 🎏 ❌, 👆 🔜 📨 ⚠ 👆 🔗.
+
+, 👆 💪 👀 👈 🎯 ⚠ 🔘 🔗 ⏮️ `except SomeException`.
+
+🎏 🌌, 👆 💪 ⚙️ `finally` ⚒ 💭 🚪 📶 🛠️, 🙅♂ 🤔 🚥 📤 ⚠ ⚖️ 🚫.
+
+```Python hl_lines="3 5"
+{!../../../docs_src/dependencies/tutorial007.py!}
+```
+
+## 🎧-🔗 ⏮️ `yield`
+
+👆 💪 ✔️ 🎧-🔗 & "🌲" 🎧-🔗 🙆 📐 & 💠, & 🙆 ⚖️ 🌐 👫 💪 ⚙️ `yield`.
+
+**FastAPI** 🔜 ⚒ 💭 👈 "🚪 📟" 🔠 🔗 ⏮️ `yield` 🏃 ☑ ✔.
+
+🖼, `dependency_c` 💪 ✔️ 🔗 🔛 `dependency_b`, & `dependency_b` 🔛 `dependency_a`:
+
+```Python hl_lines="4 12 20"
+{!../../../docs_src/dependencies/tutorial008.py!}
+```
+
+& 🌐 👫 💪 ⚙️ `yield`.
+
+👉 💼 `dependency_c`, 🛠️ 🚮 🚪 📟, 💪 💲 ⚪️➡️ `dependency_b` (📥 📛 `dep_b`) 💪.
+
+& , 🔄, `dependency_b` 💪 💲 ⚪️➡️ `dependency_a` (📥 📛 `dep_a`) 💪 🚮 🚪 📟.
+
+```Python hl_lines="16-17 24-25"
+{!../../../docs_src/dependencies/tutorial008.py!}
+```
+
+🎏 🌌, 👆 💪 ✔️ 🔗 ⏮️ `yield` & `return` 🌀.
+
+& 👆 💪 ✔️ 👁 🔗 👈 🚚 📚 🎏 🔗 ⏮️ `yield`, ♒️.
+
+👆 💪 ✔️ 🙆 🌀 🔗 👈 👆 💚.
+
+**FastAPI** 🔜 ⚒ 💭 🌐 🏃 ☑ ✔.
+
+!!! note "📡 ℹ"
+ 👉 👷 👏 🐍 🔑 👨💼.
+
+ **FastAPI** ⚙️ 👫 🔘 🏆 👉.
+
+## 🔗 ⏮️ `yield` & `HTTPException`
+
+👆 👀 👈 👆 💪 ⚙️ 🔗 ⏮️ `yield` & ✔️ `try` 🍫 👈 ✊ ⚠.
+
+⚫️ 5️⃣📆 😋 🤚 `HTTPException` ⚖️ 🎏 🚪 📟, ⏮️ `yield`. ✋️ **⚫️ 🏆 🚫 👷**.
+
+🚪 📟 🔗 ⏮️ `yield` 🛠️ *⏮️* 📨 📨, [⚠ 🐕🦺](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} 🔜 ✔️ ⏪ 🏃. 📤 🕳 😽 ⚠ 🚮 👆 🔗 🚪 📟 (⏮️ `yield`).
+
+, 🚥 👆 🤚 `HTTPException` ⏮️ `yield`, 🔢 (⚖️ 🙆 🛃) ⚠ 🐕🦺 👈 ✊ `HTTPException`Ⓜ & 📨 🇺🇸🔍 4️⃣0️⃣0️⃣ 📨 🏆 🚫 📤 ✊ 👈 ⚠ 🚫🔜.
+
+👉 ⚫️❔ ✔ 🕳 ⚒ 🔗 (✅ 💽 🎉), 🖼, ⚙️ 🖥 📋.
+
+🖥 📋 🏃 *⏮️* 📨 ✔️ 📨. 📤 🙅♂ 🌌 🤚 `HTTPException` ↩️ 📤 🚫 🌌 🔀 📨 👈 *⏪ 📨*.
+
+✋️ 🚥 🖥 📋 ✍ 💽 ❌, 🌘 👆 💪 💾 ⚖️ 😬 🔐 🎉 🔗 ⏮️ `yield`, & 🎲 🕹 ❌ ⚖️ 📄 ⚫️ 🛰 🕵 ⚙️.
+
+🚥 👆 ✔️ 📟 👈 👆 💭 💪 🤚 ⚠, 🏆 😐/"🙃" 👜 & 🚮 `try` 🍫 👈 📄 📟.
+
+🚥 👆 ✔️ 🛃 ⚠ 👈 👆 🔜 💖 🍵 *⏭* 🛬 📨 & 🎲 ❎ 📨, 🎲 🙋♀ `HTTPException`, ✍ [🛃 ⚠ 🐕🦺](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
+
+!!! tip
+ 👆 💪 🤚 ⚠ 🔌 `HTTPException` *⏭* `yield`. ✋️ 🚫 ⏮️.
+
+🔁 🛠️ 🌅 ⚖️ 🌘 💖 👉 📊. 🕰 💧 ⚪️➡️ 🔝 🔝. & 🔠 🏓 1️⃣ 🍕 🔗 ⚖️ 🛠️ 📟.
+
+```mermaid
+sequenceDiagram
+
+participant client as Client
+participant handler as Exception handler
+participant dep as Dep with yield
+participant operation as Path Operation
+participant tasks as Background tasks
+
+ Note over client,tasks: Can raise exception for dependency, handled after response is sent
+ Note over client,operation: Can raise HTTPException and can change the response
+ client ->> dep: Start request
+ Note over dep: Run code up to yield
+ opt raise
+ dep -->> handler: Raise HTTPException
+ handler -->> client: HTTP error response
+ dep -->> dep: Raise other exception
+ end
+ dep ->> operation: Run dependency, e.g. DB session
+ opt raise
+ operation -->> dep: Raise HTTPException
+ dep -->> handler: Auto forward exception
+ handler -->> client: HTTP error response
+ operation -->> dep: Raise other exception
+ dep -->> handler: Auto forward exception
+ end
+ operation ->> client: Return response to client
+ Note over client,operation: Response is already sent, can't change it anymore
+ opt Tasks
+ operation -->> tasks: Send background tasks
+ end
+ opt Raise other exception
+ tasks -->> dep: Raise other exception
+ end
+ Note over dep: After yield
+ opt Handle other exception
+ dep -->> dep: Handle exception, can't change response. E.g. close DB session.
+ end
+```
+
+!!! info
+ 🕴 **1️⃣ 📨** 🔜 📨 👩💻. ⚫️ 💪 1️⃣ ❌ 📨 ⚖️ ⚫️ 🔜 📨 ⚪️➡️ *➡ 🛠️*.
+
+ ⏮️ 1️⃣ 📚 📨 📨, 🙅♂ 🎏 📨 💪 📨.
+
+!!! tip
+ 👉 📊 🎦 `HTTPException`, ✋️ 👆 💪 🤚 🙆 🎏 ⚠ ❔ 👆 ✍ [🛃 ⚠ 🐕🦺](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
+
+ 🚥 👆 🤚 🙆 ⚠, ⚫️ 🔜 🚶♀️ 🔗 ⏮️ 🌾, 🔌 `HTTPException`, & ⤴️ **🔄** ⚠ 🐕🦺. 🚥 📤 🙅♂ ⚠ 🐕🦺 👈 ⚠, ⚫️ 🔜 ⤴️ 🍵 🔢 🔗 `ServerErrorMiddleware`, 🛬 5️⃣0️⃣0️⃣ 🇺🇸🔍 👔 📟, ➡️ 👩💻 💭 👈 📤 ❌ 💽.
+
+## 🔑 👨💼
+
+### ⚫️❔ "🔑 👨💼"
+
+"🔑 👨💼" 🙆 👈 🐍 🎚 👈 👆 💪 ⚙️ `with` 📄.
+
+🖼, 👆 💪 ⚙️ `with` ✍ 📁:
+
+```Python
+with open("./somefile.txt") as f:
+ contents = f.read()
+ print(contents)
+```
+
+🔘, `open("./somefile.txt")` ✍ 🎚 👈 🤙 "🔑 👨💼".
+
+🕐❔ `with` 🍫 🏁, ⚫️ ⚒ 💭 🔐 📁, 🚥 📤 ⚠.
+
+🕐❔ 👆 ✍ 🔗 ⏮️ `yield`, **FastAPI** 🔜 🔘 🗜 ⚫️ 🔑 👨💼, & 🌀 ⚫️ ⏮️ 🎏 🔗 🧰.
+
+### ⚙️ 🔑 👨💼 🔗 ⏮️ `yield`
+
+!!! warning
+ 👉, 🌅 ⚖️ 🌘, "🏧" 💭.
+
+ 🚥 👆 ▶️ ⏮️ **FastAPI** 👆 💪 💚 🚶 ⚫️ 🔜.
+
+🐍, 👆 💪 ✍ 🔑 👨💼 🏗 🎓 ⏮️ 2️⃣ 👩🔬: `__enter__()` & `__exit__()`.
+
+👆 💪 ⚙️ 👫 🔘 **FastAPI** 🔗 ⏮️ `yield` ⚙️
+`with` ⚖️ `async with` 📄 🔘 🔗 🔢:
+
+```Python hl_lines="1-9 13"
+{!../../../docs_src/dependencies/tutorial010.py!}
+```
+
+!!! tip
+ ➕1️⃣ 🌌 ✍ 🔑 👨💼 ⏮️:
+
+ * `@contextlib.contextmanager` ⚖️
+ * `@contextlib.asynccontextmanager`
+
+ ⚙️ 👫 🎀 🔢 ⏮️ 👁 `yield`.
+
+ 👈 ⚫️❔ **FastAPI** ⚙️ 🔘 🔗 ⏮️ `yield`.
+
+ ✋️ 👆 🚫 ✔️ ⚙️ 👨🎨 FastAPI 🔗 (& 👆 🚫🔜 🚫).
+
+ FastAPI 🔜 ⚫️ 👆 🔘.
diff --git a/docs/em/docs/tutorial/dependencies/global-dependencies.md b/docs/em/docs/tutorial/dependencies/global-dependencies.md
new file mode 100644
index 000000000..81759d0e8
--- /dev/null
+++ b/docs/em/docs/tutorial/dependencies/global-dependencies.md
@@ -0,0 +1,17 @@
+# 🌐 🔗
+
+🆎 🈸 👆 💪 💚 🚮 🔗 🎂 🈸.
+
+🎏 🌌 👆 💪 [🚮 `dependencies` *➡ 🛠️ 👨🎨*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, 👆 💪 🚮 👫 `FastAPI` 🈸.
+
+👈 💼, 👫 🔜 ✔ 🌐 *➡ 🛠️* 🈸:
+
+```Python hl_lines="15"
+{!../../../docs_src/dependencies/tutorial012.py!}
+```
+
+& 🌐 💭 📄 🔃 [❎ `dependencies` *➡ 🛠️ 👨🎨*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} ✔, ✋️ 👉 💼, 🌐 *➡ 🛠️* 📱.
+
+## 🔗 👪 *➡ 🛠️*
+
+⏪, 🕐❔ 👂 🔃 ❔ 📊 🦏 🈸 ([🦏 🈸 - 💗 📁](../../tutorial/bigger-applications.md){.internal-link target=_blank}), 🎲 ⏮️ 💗 📁, 👆 🔜 💡 ❔ 📣 👁 `dependencies` 🔢 👪 *➡ 🛠️*.
diff --git a/docs/em/docs/tutorial/dependencies/index.md b/docs/em/docs/tutorial/dependencies/index.md
new file mode 100644
index 000000000..f1c28c573
--- /dev/null
+++ b/docs/em/docs/tutorial/dependencies/index.md
@@ -0,0 +1,233 @@
+# 🔗 - 🥇 🔁
+
+**FastAPI** ✔️ 📶 🏋️ ✋️ 🏋️ **🔗 💉** ⚙️.
+
+⚫️ 🏗 📶 🙅 ⚙️, & ⚒ ⚫️ 📶 ⏩ 🙆 👩💻 🛠️ 🎏 🦲 ⏮️ **FastAPI**.
+
+## ⚫️❔ "🔗 💉"
+
+**"🔗 💉"** ⛓, 📋, 👈 📤 🌌 👆 📟 (👉 💼, 👆 *➡ 🛠️ 🔢*) 📣 👜 👈 ⚫️ 🚚 👷 & ⚙️: "🔗".
+
+& ⤴️, 👈 ⚙️ (👉 💼 **FastAPI**) 🔜 ✊ 💅 🔨 ⚫️❔ 💪 🚚 👆 📟 ⏮️ 📚 💪 🔗 ("💉" 🔗).
+
+👉 📶 ⚠ 🕐❔ 👆 💪:
+
+* ✔️ 💰 ⚛ (🎏 📟 ⚛ 🔄 & 🔄).
+* 💰 💽 🔗.
+* 🛠️ 💂♂, 🤝, 🔑 📄, ♒️.
+* & 📚 🎏 👜...
+
+🌐 👫, ⏪ 📉 📟 🔁.
+
+## 🥇 🔁
+
+➡️ 👀 📶 🙅 🖼. ⚫️ 🔜 🙅 👈 ⚫️ 🚫 📶 ⚠, 🔜.
+
+✋️ 👉 🌌 👥 💪 🎯 🔛 ❔ **🔗 💉** ⚙️ 👷.
+
+### ✍ 🔗, ⚖️ "☑"
+
+➡️ 🥇 🎯 🔛 🔗.
+
+⚫️ 🔢 👈 💪 ✊ 🌐 🎏 🔢 👈 *➡ 🛠️ 🔢* 💪 ✊:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="8-11"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="6-7"
+ {!> ../../../docs_src/dependencies/tutorial001_py310.py!}
+ ```
+
+👈 ⚫️.
+
+**2️⃣ ⏸**.
+
+& ⚫️ ✔️ 🎏 💠 & 📊 👈 🌐 👆 *➡ 🛠️ 🔢* ✔️.
+
+👆 💪 💭 ⚫️ *➡ 🛠️ 🔢* 🍵 "👨🎨" (🍵 `@app.get("/some-path")`).
+
+& ⚫️ 💪 📨 🕳 👆 💚.
+
+👉 💼, 👉 🔗 ⌛:
+
+* 📦 🔢 🔢 `q` 👈 `str`.
+* 📦 🔢 🔢 `skip` 👈 `int`, & 🔢 `0`.
+* 📦 🔢 🔢 `limit` 👈 `int`, & 🔢 `100`.
+
+& ⤴️ ⚫️ 📨 `dict` ⚗ 📚 💲.
+
+### 🗄 `Depends`
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/dependencies/tutorial001_py310.py!}
+ ```
+
+### 📣 🔗, "⚓️"
+
+🎏 🌌 👆 ⚙️ `Body`, `Query`, ♒️. ⏮️ 👆 *➡ 🛠️ 🔢* 🔢, ⚙️ `Depends` ⏮️ 🆕 🔢:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="15 20"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="11 16"
+ {!> ../../../docs_src/dependencies/tutorial001_py310.py!}
+ ```
+
+👐 👆 ⚙️ `Depends` 🔢 👆 🔢 🎏 🌌 👆 ⚙️ `Body`, `Query`, ♒️, `Depends` 👷 👄 🎏.
+
+👆 🕴 🤝 `Depends` 👁 🔢.
+
+👉 🔢 🔜 🕳 💖 🔢.
+
+& 👈 🔢 ✊ 🔢 🎏 🌌 👈 *➡ 🛠️ 🔢* .
+
+!!! tip
+ 👆 🔜 👀 ⚫️❔ 🎏 "👜", ↖️ ⚪️➡️ 🔢, 💪 ⚙️ 🔗 ⏭ 📃.
+
+🕐❔ 🆕 📨 🛬, **FastAPI** 🔜 ✊ 💅:
+
+* 🤙 👆 🔗 ("☑") 🔢 ⏮️ ☑ 🔢.
+* 🤚 🏁 ⚪️➡️ 👆 🔢.
+* 🛠️ 👈 🏁 🔢 👆 *➡ 🛠️ 🔢*.
+
+```mermaid
+graph TB
+
+common_parameters(["common_parameters"])
+read_items["/items/"]
+read_users["/users/"]
+
+common_parameters --> read_items
+common_parameters --> read_users
+```
+
+👉 🌌 👆 ✍ 🔗 📟 🕐 & **FastAPI** ✊ 💅 🤙 ⚫️ 👆 *➡ 🛠️*.
+
+!!! check
+ 👀 👈 👆 🚫 ✔️ ✍ 🎁 🎓 & 🚶♀️ ⚫️ 👱 **FastAPI** "®" ⚫️ ⚖️ 🕳 🎏.
+
+ 👆 🚶♀️ ⚫️ `Depends` & **FastAPI** 💭 ❔ 🎂.
+
+## `async` ⚖️ 🚫 `async`
+
+🔗 🔜 🤙 **FastAPI** (🎏 👆 *➡ 🛠️ 🔢*), 🎏 🚫 ✔ ⏪ 🔬 👆 🔢.
+
+👆 💪 ⚙️ `async def` ⚖️ 😐 `def`.
+
+& 👆 💪 📣 🔗 ⏮️ `async def` 🔘 😐 `def` *➡ 🛠️ 🔢*, ⚖️ `def` 🔗 🔘 `async def` *➡ 🛠️ 🔢*, ♒️.
+
+⚫️ 🚫 🤔. **FastAPI** 🔜 💭 ⚫️❔.
+
+!!! note
+ 🚥 👆 🚫 💭, ✅ [🔁: *"🏃 ❓" *](../../async.md){.internal-link target=_blank} 📄 🔃 `async` & `await` 🩺.
+
+## 🛠️ ⏮️ 🗄
+
+🌐 📨 📄, 🔬 & 📄 👆 🔗 (& 🎧-🔗) 🔜 🛠️ 🎏 🗄 🔗.
+
+, 🎓 🩺 🔜 ✔️ 🌐 ℹ ⚪️➡️ 👫 🔗 💁♂️:
+
+
+
+## 🙅 ⚙️
+
+🚥 👆 👀 ⚫️, *➡ 🛠️ 🔢* 📣 ⚙️ 🕐❔ *➡* & *🛠️* 🏏, & ⤴️ **FastAPI** ✊ 💅 🤙 🔢 ⏮️ ☑ 🔢, ❎ 📊 ⚪️➡️ 📨.
+
+🤙, 🌐 (⚖️ 🏆) 🕸 🛠️ 👷 👉 🎏 🌌.
+
+👆 🙅 🤙 👈 🔢 🔗. 👫 🤙 👆 🛠️ (👉 💼, **FastAPI**).
+
+⏮️ 🔗 💉 ⚙️, 👆 💪 💬 **FastAPI** 👈 👆 *➡ 🛠️ 🔢* "🪀" 🔛 🕳 🙆 👈 🔜 🛠️ ⏭ 👆 *➡ 🛠️ 🔢*, & **FastAPI** 🔜 ✊ 💅 🛠️ ⚫️ & "💉" 🏁.
+
+🎏 ⚠ ⚖ 👉 🎏 💭 "🔗 💉":
+
+* ℹ
+* 🐕🦺
+* 🐕🦺
+* 💉
+* 🦲
+
+## **FastAPI** 🔌-🔌
+
+🛠️ & "🔌-"Ⓜ 💪 🏗 ⚙️ **🔗 💉** ⚙️. ✋️ 👐, 📤 🤙 **🙅♂ 💪 ✍ "🔌-🔌"**, ⚙️ 🔗 ⚫️ 💪 📣 ♾ 🔢 🛠️ & 🔗 👈 ▶️️ 💪 👆 *➡ 🛠️ 🔢*.
+
+& 🔗 💪 ✍ 📶 🙅 & 🏋️ 🌌 👈 ✔ 👆 🗄 🐍 📦 👆 💪, & 🛠️ 👫 ⏮️ 👆 🛠️ 🔢 👩❤👨 ⏸ 📟, *🌖*.
+
+👆 🔜 👀 🖼 👉 ⏭ 📃, 🔃 🔗 & ☁ 💽, 💂♂, ♒️.
+
+## **FastAPI** 🔗
+
+🦁 🔗 💉 ⚙️ ⚒ **FastAPI** 🔗 ⏮️:
+
+* 🌐 🔗 💽
+* ☁ 💽
+* 🔢 📦
+* 🔢 🔗
+* 🤝 & ✔ ⚙️
+* 🛠️ ⚙️ ⚖ ⚙️
+* 📨 💽 💉 ⚙️
+* ♒️.
+
+## 🙅 & 🏋️
+
+👐 🔗 🔗 💉 ⚙️ 📶 🙅 🔬 & ⚙️, ⚫️ 📶 🏋️.
+
+👆 💪 🔬 🔗 👈 🔄 💪 🔬 🔗 👫.
+
+🔚, 🔗 🌲 🔗 🏗, & **🔗 💉** ⚙️ ✊ 💅 🔬 🌐 👉 🔗 👆 (& 👫 🎧-🔗) & 🚚 (💉) 🏁 🔠 🔁.
+
+🖼, ➡️ 💬 👆 ✔️ 4️⃣ 🛠️ 🔗 (*➡ 🛠️*):
+
+* `/items/public/`
+* `/items/private/`
+* `/users/{user_id}/activate`
+* `/items/pro/`
+
+⤴️ 👆 💪 🚮 🎏 ✔ 📄 🔠 👫 ⏮️ 🔗 & 🎧-🔗:
+
+```mermaid
+graph TB
+
+current_user(["current_user"])
+active_user(["active_user"])
+admin_user(["admin_user"])
+paying_user(["paying_user"])
+
+public["/items/public/"]
+private["/items/private/"]
+activate_user["/users/{user_id}/activate"]
+pro_items["/items/pro/"]
+
+current_user --> active_user
+active_user --> admin_user
+active_user --> paying_user
+
+current_user --> public
+active_user --> private
+admin_user --> activate_user
+paying_user --> pro_items
+```
+
+## 🛠️ ⏮️ **🗄**
+
+🌐 👫 🔗, ⏪ 📣 👫 📄, 🚮 🔢, 🔬, ♒️. 👆 *➡ 🛠️*.
+
+**FastAPI** 🔜 ✊ 💅 🚮 ⚫️ 🌐 🗄 🔗, 👈 ⚫️ 🎦 🎓 🧾 ⚙️.
diff --git a/docs/em/docs/tutorial/dependencies/sub-dependencies.md b/docs/em/docs/tutorial/dependencies/sub-dependencies.md
new file mode 100644
index 000000000..454ff5129
--- /dev/null
+++ b/docs/em/docs/tutorial/dependencies/sub-dependencies.md
@@ -0,0 +1,110 @@
+# 🎧-🔗
+
+👆 💪 ✍ 🔗 👈 ✔️ **🎧-🔗**.
+
+👫 💪 **⏬** 👆 💪 👫.
+
+**FastAPI** 🔜 ✊ 💅 🔬 👫.
+
+## 🥇 🔗 "☑"
+
+👆 💪 ✍ 🥇 🔗 ("☑") 💖:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="8-9"
+ {!> ../../../docs_src/dependencies/tutorial005.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="6-7"
+ {!> ../../../docs_src/dependencies/tutorial005_py310.py!}
+ ```
+
+⚫️ 📣 📦 🔢 🔢 `q` `str`, & ⤴️ ⚫️ 📨 ⚫️.
+
+👉 🙅 (🚫 📶 ⚠), ✋️ 🔜 ℹ 👥 🎯 🔛 ❔ 🎧-🔗 👷.
+
+## 🥈 🔗, "☑" & "⚓️"
+
+⤴️ 👆 💪 ✍ ➕1️⃣ 🔗 🔢 ("☑") 👈 🎏 🕰 📣 🔗 🚮 👍 (⚫️ "⚓️" 💁♂️):
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/dependencies/tutorial005.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/dependencies/tutorial005_py310.py!}
+ ```
+
+➡️ 🎯 🔛 🔢 📣:
+
+* ✋️ 👉 🔢 🔗 ("☑") ⚫️, ⚫️ 📣 ➕1️⃣ 🔗 (⚫️ "🪀" 🔛 🕳 🙆).
+ * ⚫️ 🪀 🔛 `query_extractor`, & 🛠️ 💲 📨 ⚫️ 🔢 `q`.
+* ⚫️ 📣 📦 `last_query` 🍪, `str`.
+ * 🚥 👩💻 🚫 🚚 🙆 🔢 `q`, 👥 ⚙️ 🏁 🔢 ⚙️, ❔ 👥 🖊 🍪 ⏭.
+
+## ⚙️ 🔗
+
+⤴️ 👥 💪 ⚙️ 🔗 ⏮️:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/dependencies/tutorial005.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial005_py310.py!}
+ ```
+
+!!! info
+ 👀 👈 👥 🕴 📣 1️⃣ 🔗 *➡ 🛠️ 🔢*, `query_or_cookie_extractor`.
+
+ ✋️ **FastAPI** 🔜 💭 👈 ⚫️ ✔️ ❎ `query_extractor` 🥇, 🚶♀️ 🏁 👈 `query_or_cookie_extractor` ⏪ 🤙 ⚫️.
+
+```mermaid
+graph TB
+
+query_extractor(["query_extractor"])
+query_or_cookie_extractor(["query_or_cookie_extractor"])
+
+read_query["/items/"]
+
+query_extractor --> query_or_cookie_extractor --> read_query
+```
+
+## ⚙️ 🎏 🔗 💗 🕰
+
+🚥 1️⃣ 👆 🔗 📣 💗 🕰 🎏 *➡ 🛠️*, 🖼, 💗 🔗 ✔️ ⚠ 🎧-🔗, **FastAPI** 🔜 💭 🤙 👈 🎧-🔗 🕴 🕐 📍 📨.
+
+& ⚫️ 🔜 🖊 📨 💲 "💾" & 🚶♀️ ⚫️ 🌐 "⚓️" 👈 💪 ⚫️ 👈 🎯 📨, ↩️ 🤙 🔗 💗 🕰 🎏 📨.
+
+🏧 😐 🌐❔ 👆 💭 👆 💪 🔗 🤙 🔠 🔁 (🎲 💗 🕰) 🎏 📨 ↩️ ⚙️ "💾" 💲, 👆 💪 ⚒ 🔢 `use_cache=False` 🕐❔ ⚙️ `Depends`:
+
+```Python hl_lines="1"
+async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):
+ return {"fresh_value": fresh_value}
+```
+
+## 🌃
+
+↖️ ⚪️➡️ 🌐 🎀 🔤 ⚙️ 📥, **🔗 💉** ⚙️ 🙅.
+
+🔢 👈 👀 🎏 *➡ 🛠️ 🔢*.
+
+✋️, ⚫️ 📶 🏋️, & ✔ 👆 📣 🎲 🙇 🐦 🔗 "📊" (🌲).
+
+!!! tip
+ 🌐 👉 💪 🚫 😑 ⚠ ⏮️ 👫 🙅 🖼.
+
+ ✋️ 👆 🔜 👀 ❔ ⚠ ⚫️ 📃 🔃 **💂♂**.
+
+ & 👆 🔜 👀 💸 📟 ⚫️ 🔜 🖊 👆.
diff --git a/docs/em/docs/tutorial/encoder.md b/docs/em/docs/tutorial/encoder.md
new file mode 100644
index 000000000..75ca3824d
--- /dev/null
+++ b/docs/em/docs/tutorial/encoder.md
@@ -0,0 +1,42 @@
+# 🎻 🔗 🔢
+
+📤 💼 🌐❔ 👆 5️⃣📆 💪 🗜 💽 🆎 (💖 Pydantic 🏷) 🕳 🔗 ⏮️ 🎻 (💖 `dict`, `list`, ♒️).
+
+🖼, 🚥 👆 💪 🏪 ⚫️ 💽.
+
+👈, **FastAPI** 🚚 `jsonable_encoder()` 🔢.
+
+## ⚙️ `jsonable_encoder`
+
+➡️ 🌈 👈 👆 ✔️ 💽 `fake_db` 👈 🕴 📨 🎻 🔗 💽.
+
+🖼, ⚫️ 🚫 📨 `datetime` 🎚, 👈 🚫 🔗 ⏮️ 🎻.
+
+, `datetime` 🎚 🔜 ✔️ 🗜 `str` ⚗ 💽 💾 📁.
+
+🎏 🌌, 👉 💽 🚫🔜 📨 Pydantic 🏷 (🎚 ⏮️ 🔢), 🕴 `dict`.
+
+👆 💪 ⚙️ `jsonable_encoder` 👈.
+
+⚫️ 📨 🎚, 💖 Pydantic 🏷, & 📨 🎻 🔗 ⏬:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="5 22"
+ {!> ../../../docs_src/encoder/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="4 21"
+ {!> ../../../docs_src/encoder/tutorial001_py310.py!}
+ ```
+
+👉 🖼, ⚫️ 🔜 🗜 Pydantic 🏷 `dict`, & `datetime` `str`.
+
+🏁 🤙 ⚫️ 🕳 👈 💪 🗜 ⏮️ 🐍 🐩 `json.dumps()`.
+
+⚫️ 🚫 📨 ⭕ `str` ⚗ 💽 🎻 📁 (🎻). ⚫️ 📨 🐍 🐩 💽 📊 (✅ `dict`) ⏮️ 💲 & 🎧-💲 👈 🌐 🔗 ⏮️ 🎻.
+
+!!! note
+ `jsonable_encoder` 🤙 ⚙️ **FastAPI** 🔘 🗜 💽. ✋️ ⚫️ ⚠ 📚 🎏 😐.
diff --git a/docs/em/docs/tutorial/extra-data-types.md b/docs/em/docs/tutorial/extra-data-types.md
new file mode 100644
index 000000000..dfdf6141b
--- /dev/null
+++ b/docs/em/docs/tutorial/extra-data-types.md
@@ -0,0 +1,82 @@
+# ➕ 💽 🆎
+
+🆙 🔜, 👆 ✔️ ⚙️ ⚠ 📊 🆎, 💖:
+
+* `int`
+* `float`
+* `str`
+* `bool`
+
+✋️ 👆 💪 ⚙️ 🌅 🏗 📊 🆎.
+
+& 👆 🔜 ✔️ 🎏 ⚒ 👀 🆙 🔜:
+
+* 👑 👨🎨 🐕🦺.
+* 💽 🛠️ ⚪️➡️ 📨 📨.
+* 💽 🛠️ 📨 💽.
+* 💽 🔬.
+* 🏧 ✍ & 🧾.
+
+## 🎏 💽 🆎
+
+📥 🌖 📊 🆎 👆 💪 ⚙️:
+
+* `UUID`:
+ * 🐩 "⭐ 😍 🆔", ⚠ 🆔 📚 💽 & ⚙️.
+ * 📨 & 📨 🔜 🎨 `str`.
+* `datetime.datetime`:
+ * 🐍 `datetime.datetime`.
+ * 📨 & 📨 🔜 🎨 `str` 💾 8️⃣6️⃣0️⃣1️⃣ 📁, 💖: `2008-09-15T15:53:00+05:00`.
+* `datetime.date`:
+ * 🐍 `datetime.date`.
+ * 📨 & 📨 🔜 🎨 `str` 💾 8️⃣6️⃣0️⃣1️⃣ 📁, 💖: `2008-09-15`.
+* `datetime.time`:
+ * 🐍 `datetime.time`.
+ * 📨 & 📨 🔜 🎨 `str` 💾 8️⃣6️⃣0️⃣1️⃣ 📁, 💖: `14:23:55.003`.
+* `datetime.timedelta`:
+ * 🐍 `datetime.timedelta`.
+ * 📨 & 📨 🔜 🎨 `float` 🌐 🥈.
+ * Pydantic ✔ 🎦 ⚫️ "💾 8️⃣6️⃣0️⃣1️⃣ 🕰 ➕ 🔢", 👀 🩺 🌅 ℹ.
+* `frozenset`:
+ * 📨 & 📨, 😥 🎏 `set`:
+ * 📨, 📇 🔜 ✍, ❎ ❎ & 🏭 ⚫️ `set`.
+ * 📨, `set` 🔜 🗜 `list`.
+ * 🏗 🔗 🔜 ✔ 👈 `set` 💲 😍 (⚙️ 🎻 🔗 `uniqueItems`).
+* `bytes`:
+ * 🐩 🐍 `bytes`.
+ * 📨 & 📨 🔜 😥 `str`.
+ * 🏗 🔗 🔜 ✔ 👈 ⚫️ `str` ⏮️ `binary` "📁".
+* `Decimal`:
+ * 🐩 🐍 `Decimal`.
+ * 📨 & 📨, 🍵 🎏 `float`.
+* 👆 💪 ✅ 🌐 ☑ Pydantic 📊 🆎 📥: Pydantic 📊 🆎.
+
+## 🖼
+
+📥 🖼 *➡ 🛠️* ⏮️ 🔢 ⚙️ 🔛 🆎.
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="1 3 12-16"
+ {!> ../../../docs_src/extra_data_types/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="1 2 11-15"
+ {!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
+ ```
+
+🗒 👈 🔢 🔘 🔢 ✔️ 👫 🐠 💽 🆎, & 👆 💪, 🖼, 🎭 😐 📅 🎭, 💖:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="18-19"
+ {!> ../../../docs_src/extra_data_types/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="17-18"
+ {!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
+ ```
diff --git a/docs/em/docs/tutorial/extra-models.md b/docs/em/docs/tutorial/extra-models.md
new file mode 100644
index 000000000..06c36285d
--- /dev/null
+++ b/docs/em/docs/tutorial/extra-models.md
@@ -0,0 +1,252 @@
+# ➕ 🏷
+
+▶️ ⏮️ ⏮️ 🖼, ⚫️ 🔜 ⚠ ✔️ 🌅 🌘 1️⃣ 🔗 🏷.
+
+👉 ✴️ 💼 👩💻 🏷, ↩️:
+
+* **🔢 🏷** 💪 💪 ✔️ 🔐.
+* **🔢 🏷** 🔜 🚫 ✔️ 🔐.
+* **💽 🏷** 🔜 🎲 💪 ✔️ #️⃣ 🔐.
+
+!!! danger
+ 🙅 🏪 👩💻 🔢 🔐. 🕧 🏪 "🔐 #️⃣" 👈 👆 💪 ⤴️ ✔.
+
+ 🚥 👆 🚫 💭, 👆 🔜 💡 ⚫️❔ "🔐#️⃣" [💂♂ 📃](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}.
+
+## 💗 🏷
+
+📥 🏢 💭 ❔ 🏷 💪 👀 💖 ⏮️ 👫 🔐 🏑 & 🥉 🌐❔ 👫 ⚙️:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
+ {!> ../../../docs_src/extra_models/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7 9 14 20 22 27-28 31-33 38-39"
+ {!> ../../../docs_src/extra_models/tutorial001_py310.py!}
+ ```
+
+### 🔃 `**user_in.dict()`
+
+#### Pydantic `.dict()`
+
+`user_in` Pydantic 🏷 🎓 `UserIn`.
+
+Pydantic 🏷 ✔️ `.dict()` 👩🔬 👈 📨 `dict` ⏮️ 🏷 💽.
+
+, 🚥 👥 ✍ Pydantic 🎚 `user_in` 💖:
+
+```Python
+user_in = UserIn(username="john", password="secret", email="john.doe@example.com")
+```
+
+& ⤴️ 👥 🤙:
+
+```Python
+user_dict = user_in.dict()
+```
+
+👥 🔜 ✔️ `dict` ⏮️ 💽 🔢 `user_dict` (⚫️ `dict` ↩️ Pydantic 🏷 🎚).
+
+& 🚥 👥 🤙:
+
+```Python
+print(user_dict)
+```
+
+👥 🔜 🤚 🐍 `dict` ⏮️:
+
+```Python
+{
+ 'username': 'john',
+ 'password': 'secret',
+ 'email': 'john.doe@example.com',
+ 'full_name': None,
+}
+```
+
+#### 🎁 `dict`
+
+🚥 👥 ✊ `dict` 💖 `user_dict` & 🚶♀️ ⚫️ 🔢 (⚖️ 🎓) ⏮️ `**user_dict`, 🐍 🔜 "🎁" ⚫️. ⚫️ 🔜 🚶♀️ 🔑 & 💲 `user_dict` 🔗 🔑-💲 ❌.
+
+, ▶️ ⏮️ `user_dict` ⚪️➡️ 🔛, ✍:
+
+```Python
+UserInDB(**user_dict)
+```
+
+🔜 🏁 🕳 🌓:
+
+```Python
+UserInDB(
+ username="john",
+ password="secret",
+ email="john.doe@example.com",
+ full_name=None,
+)
+```
+
+⚖️ 🌅 ⚫️❔, ⚙️ `user_dict` 🔗, ⏮️ ⚫️❔ 🎚 ⚫️ 💪 ✔️ 🔮:
+
+```Python
+UserInDB(
+ username = user_dict["username"],
+ password = user_dict["password"],
+ email = user_dict["email"],
+ full_name = user_dict["full_name"],
+)
+```
+
+#### Pydantic 🏷 ⚪️➡️ 🎚 ➕1️⃣
+
+🖼 🔛 👥 🤚 `user_dict` ⚪️➡️ `user_in.dict()`, 👉 📟:
+
+```Python
+user_dict = user_in.dict()
+UserInDB(**user_dict)
+```
+
+🔜 🌓:
+
+```Python
+UserInDB(**user_in.dict())
+```
+
+...↩️ `user_in.dict()` `dict`, & ⤴️ 👥 ⚒ 🐍 "🎁" ⚫️ 🚶♀️ ⚫️ `UserInDB` 🔠 ⏮️ `**`.
+
+, 👥 🤚 Pydantic 🏷 ⚪️➡️ 💽 ➕1️⃣ Pydantic 🏷.
+
+#### 🎁 `dict` & ➕ 🇨🇻
+
+& ⤴️ ❎ ➕ 🇨🇻 ❌ `hashed_password=hashed_password`, 💖:
+
+```Python
+UserInDB(**user_in.dict(), hashed_password=hashed_password)
+```
+
+...🔚 🆙 💆♂ 💖:
+
+```Python
+UserInDB(
+ username = user_dict["username"],
+ password = user_dict["password"],
+ email = user_dict["email"],
+ full_name = user_dict["full_name"],
+ hashed_password = hashed_password,
+)
+```
+
+!!! warning
+ 🔗 🌖 🔢 🤖 💪 💧 💽, ✋️ 👫 ↗️ 🚫 🚚 🙆 🎰 💂♂.
+
+## 📉 ❎
+
+📉 📟 ❎ 1️⃣ 🐚 💭 **FastAPI**.
+
+📟 ❎ 📈 🤞 🐛, 💂♂ ❔, 📟 🔁 ❔ (🕐❔ 👆 ℹ 1️⃣ 🥉 ✋️ 🚫 🎏), ♒️.
+
+& 👉 🏷 🌐 🤝 📚 💽 & ❎ 🔢 📛 & 🆎.
+
+👥 💪 👻.
+
+👥 💪 📣 `UserBase` 🏷 👈 🍦 🧢 👆 🎏 🏷. & ⤴️ 👥 💪 ⚒ 🏿 👈 🏷 👈 😖 🚮 🔢 (🆎 📄, 🔬, ♒️).
+
+🌐 💽 🛠️, 🔬, 🧾, ♒️. 🔜 👷 🛎.
+
+👈 🌌, 👥 💪 📣 🔺 🖖 🏷 (⏮️ 🔢 `password`, ⏮️ `hashed_password` & 🍵 🔐):
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9 15-16 19-20 23-24"
+ {!> ../../../docs_src/extra_models/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7 13-14 17-18 21-22"
+ {!> ../../../docs_src/extra_models/tutorial002_py310.py!}
+ ```
+
+## `Union` ⚖️ `anyOf`
+
+👆 💪 📣 📨 `Union` 2️⃣ 🆎, 👈 ⛓, 👈 📨 🔜 🙆 2️⃣.
+
+⚫️ 🔜 🔬 🗄 ⏮️ `anyOf`.
+
+👈, ⚙️ 🐩 🐍 🆎 🔑 `typing.Union`:
+
+!!! note
+ 🕐❔ ⚖ `Union`, 🔌 🏆 🎯 🆎 🥇, ⏩ 🌘 🎯 🆎. 🖼 🔛, 🌖 🎯 `PlaneItem` 👟 ⏭ `CarItem` `Union[PlaneItem, CarItem]`.
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="1 14-15 18-20 33"
+ {!> ../../../docs_src/extra_models/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="1 14-15 18-20 33"
+ {!> ../../../docs_src/extra_models/tutorial003_py310.py!}
+ ```
+
+### `Union` 🐍 3️⃣.1️⃣0️⃣
+
+👉 🖼 👥 🚶♀️ `Union[PlaneItem, CarItem]` 💲 ❌ `response_model`.
+
+↩️ 👥 🚶♀️ ⚫️ **💲 ❌** ↩️ 🚮 ⚫️ **🆎 ✍**, 👥 ✔️ ⚙️ `Union` 🐍 3️⃣.1️⃣0️⃣.
+
+🚥 ⚫️ 🆎 ✍ 👥 💪 ✔️ ⚙️ ⏸ ⏸,:
+
+```Python
+some_variable: PlaneItem | CarItem
+```
+
+✋️ 🚥 👥 🚮 👈 `response_model=PlaneItem | CarItem` 👥 🔜 🤚 ❌, ↩️ 🐍 🔜 🔄 🎭 **❌ 🛠️** 🖖 `PlaneItem` & `CarItem` ↩️ 🔬 👈 🆎 ✍.
+
+## 📇 🏷
+
+🎏 🌌, 👆 💪 📣 📨 📇 🎚.
+
+👈, ⚙️ 🐩 🐍 `typing.List` (⚖️ `list` 🐍 3️⃣.9️⃣ & 🔛):
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="1 20"
+ {!> ../../../docs_src/extra_models/tutorial004.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/extra_models/tutorial004_py39.py!}
+ ```
+
+## 📨 ⏮️ ❌ `dict`
+
+👆 💪 📣 📨 ⚙️ ✅ ❌ `dict`, 📣 🆎 🔑 & 💲, 🍵 ⚙️ Pydantic 🏷.
+
+👉 ⚠ 🚥 👆 🚫 💭 ☑ 🏑/🔢 📛 (👈 🔜 💪 Pydantic 🏷) ⏪.
+
+👉 💼, 👆 💪 ⚙️ `typing.Dict` (⚖️ `dict` 🐍 3️⃣.9️⃣ & 🔛):
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="1 8"
+ {!> ../../../docs_src/extra_models/tutorial005.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="6"
+ {!> ../../../docs_src/extra_models/tutorial005_py39.py!}
+ ```
+
+## 🌃
+
+⚙️ 💗 Pydantic 🏷 & 😖 ➡ 🔠 💼.
+
+👆 🚫 💪 ✔️ 👁 💽 🏷 📍 👨💼 🚥 👈 👨💼 🔜 💪 ✔️ 🎏 "🇵🇸". 💼 ⏮️ 👩💻 "👨💼" ⏮️ 🇵🇸 ✅ `password`, `password_hash` & 🙅♂ 🔐.
diff --git a/docs/em/docs/tutorial/first-steps.md b/docs/em/docs/tutorial/first-steps.md
new file mode 100644
index 000000000..252e769f4
--- /dev/null
+++ b/docs/em/docs/tutorial/first-steps.md
@@ -0,0 +1,333 @@
+# 🥇 🔁
+
+🙅 FastAPI 📁 💪 👀 💖 👉:
+
+```Python
+{!../../../docs_src/first_steps/tutorial001.py!}
+```
+
+📁 👈 📁 `main.py`.
+
+🏃 🖖 💽:
+
+get 🛠️
+
+!!! info "`@decorator` ℹ"
+ 👈 `@something` ❕ 🐍 🤙 "👨🎨".
+
+ 👆 🚮 ⚫️ 🔛 🔝 🔢. 💖 📶 📔 👒 (👤 💭 👈 🌐❔ ⚖ 👟 ⚪️➡️).
+
+ "👨🎨" ✊ 🔢 🔛 & 🔨 🕳 ⏮️ ⚫️.
+
+ 👆 💼, 👉 👨🎨 💬 **FastAPI** 👈 🔢 🔛 🔗 **➡** `/` ⏮️ **🛠️** `get`.
+
+ ⚫️ "**➡ 🛠️ 👨🎨**".
+
+👆 💪 ⚙️ 🎏 🛠️:
+
+* `@app.post()`
+* `@app.put()`
+* `@app.delete()`
+
+& 🌅 😍 🕐:
+
+* `@app.options()`
+* `@app.head()`
+* `@app.patch()`
+* `@app.trace()`
+
+!!! tip
+ 👆 🆓 ⚙️ 🔠 🛠️ (🇺🇸🔍 👩🔬) 👆 🎋.
+
+ **FastAPI** 🚫 🛠️ 🙆 🎯 🔑.
+
+ ℹ 📥 🎁 📄, 🚫 📄.
+
+ 🖼, 🕐❔ ⚙️ 🕹 👆 🛎 🎭 🌐 🎯 ⚙️ 🕴 `POST` 🛠️.
+
+### 🔁 4️⃣: 🔬 **➡ 🛠️ 🔢**
+
+👉 👆 "**➡ 🛠️ 🔢**":
+
+* **➡**: `/`.
+* **🛠️**: `get`.
+* **🔢**: 🔢 🔛 "👨🎨" (🔛 `@app.get("/")`).
+
+```Python hl_lines="7"
+{!../../../docs_src/first_steps/tutorial001.py!}
+```
+
+👉 🐍 🔢.
+
+⚫️ 🔜 🤙 **FastAPI** 🕐❔ ⚫️ 📨 📨 📛 "`/`" ⚙️ `GET` 🛠️.
+
+👉 💼, ⚫️ `async` 🔢.
+
+---
+
+👆 💪 🔬 ⚫️ 😐 🔢 ↩️ `async def`:
+
+```Python hl_lines="7"
+{!../../../docs_src/first_steps/tutorial003.py!}
+```
+
+!!! note
+ 🚥 👆 🚫 💭 🔺, ✅ [🔁: *"🏃 ❓"*](../async.md#in-a-hurry){.internal-link target=_blank}.
+
+### 🔁 5️⃣: 📨 🎚
+
+```Python hl_lines="8"
+{!../../../docs_src/first_steps/tutorial001.py!}
+```
+
+👆 💪 📨 `dict`, `list`, ⭐ 💲 `str`, `int`, ♒️.
+
+👆 💪 📨 Pydantic 🏷 (👆 🔜 👀 🌅 🔃 👈 ⏪).
+
+📤 📚 🎏 🎚 & 🏷 👈 🔜 🔁 🗜 🎻 (🔌 🐜, ♒️). 🔄 ⚙️ 👆 💕 🕐, ⚫️ 🏆 🎲 👈 👫 ⏪ 🐕🦺.
+
+## 🌃
+
+* 🗄 `FastAPI`.
+* ✍ `app` 👐.
+* ✍ **➡ 🛠️ 👨🎨** (💖 `@app.get("/")`).
+* ✍ **➡ 🛠️ 🔢** (💖 `def root(): ...` 🔛).
+* 🏃 🛠️ 💽 (💖 `uvicorn main:app --reload`).
diff --git a/docs/em/docs/tutorial/handling-errors.md b/docs/em/docs/tutorial/handling-errors.md
new file mode 100644
index 000000000..ef7bbfa65
--- /dev/null
+++ b/docs/em/docs/tutorial/handling-errors.md
@@ -0,0 +1,261 @@
+# 🚚 ❌
+
+📤 📚 ⚠ 🌐❔ 👆 💪 🚨 ❌ 👩💻 👈 ⚙️ 👆 🛠️.
+
+👉 👩💻 💪 🖥 ⏮️ 🕸, 📟 ⚪️➡️ 👱 🙆, ☁ 📳, ♒️.
+
+👆 💪 💪 💬 👩💻 👈:
+
+* 👩💻 🚫 ✔️ 🥃 😌 👈 🛠️.
+* 👩💻 🚫 ✔️ 🔐 👈 ℹ.
+* 🏬 👩💻 🔄 🔐 🚫 🔀.
+* ♒️.
+
+👫 💼, 👆 🔜 🛎 📨 **🇺🇸🔍 👔 📟** ↔ **4️⃣0️⃣0️⃣** (⚪️➡️ 4️⃣0️⃣0️⃣ 4️⃣9️⃣9️⃣).
+
+👉 🎏 2️⃣0️⃣0️⃣ 🇺🇸🔍 👔 📟 (⚪️➡️ 2️⃣0️⃣0️⃣ 2️⃣9️⃣9️⃣). 👈 "2️⃣0️⃣0️⃣" 👔 📟 ⛓ 👈 😫 📤 "🏆" 📨.
+
+👔 📟 4️⃣0️⃣0️⃣ ↔ ⛓ 👈 📤 ❌ ⚪️➡️ 👩💻.
+
+💭 🌐 👈 **"4️⃣0️⃣4️⃣ 🚫 🔎"** ❌ (& 🤣) ❓
+
+## ⚙️ `HTTPException`
+
+📨 🇺🇸🔍 📨 ⏮️ ❌ 👩💻 👆 ⚙️ `HTTPException`.
+
+### 🗄 `HTTPException`
+
+```Python hl_lines="1"
+{!../../../docs_src/handling_errors/tutorial001.py!}
+```
+
+### 🤚 `HTTPException` 👆 📟
+
+`HTTPException` 😐 🐍 ⚠ ⏮️ 🌖 📊 🔗 🔗.
+
+↩️ ⚫️ 🐍 ⚠, 👆 🚫 `return` ⚫️, 👆 `raise` ⚫️.
+
+👉 ⛓ 👈 🚥 👆 🔘 🚙 🔢 👈 👆 🤙 🔘 👆 *➡ 🛠️ 🔢*, & 👆 🤚 `HTTPException` ⚪️➡️ 🔘 👈 🚙 🔢, ⚫️ 🏆 🚫 🏃 🎂 📟 *➡ 🛠️ 🔢*, ⚫️ 🔜 ❎ 👈 📨 ▶️️ ↖️ & 📨 🇺🇸🔍 ❌ ⚪️➡️ `HTTPException` 👩💻.
+
+💰 🙋♀ ⚠ 🤭 `return`😅 💲 🔜 🌖 ⭐ 📄 🔃 🔗 & 💂♂.
+
+👉 🖼, 🕐❔ 👩💻 📨 🏬 🆔 👈 🚫 🔀, 🤚 ⚠ ⏮️ 👔 📟 `404`:
+
+```Python hl_lines="11"
+{!../../../docs_src/handling_errors/tutorial001.py!}
+```
+
+### 📉 📨
+
+🚥 👩💻 📨 `http://example.com/items/foo` ( `item_id` `"foo"`), 👈 👩💻 🔜 📨 🇺🇸🔍 👔 📟 2️⃣0️⃣0️⃣, & 🎻 📨:
+
+```JSON
+{
+ "item": "The Foo Wrestlers"
+}
+```
+
+✋️ 🚥 👩💻 📨 `http://example.com/items/bar` (🚫-🚫 `item_id` `"bar"`), 👈 👩💻 🔜 📨 🇺🇸🔍 👔 📟 4️⃣0️⃣4️⃣ ("🚫 🔎" ❌), & 🎻 📨:
+
+```JSON
+{
+ "detail": "Item not found"
+}
+```
+
+!!! tip
+ 🕐❔ 🙋♀ `HTTPException`, 👆 💪 🚶♀️ 🙆 💲 👈 💪 🗜 🎻 🔢 `detail`, 🚫 🕴 `str`.
+
+ 👆 💪 🚶♀️ `dict`, `list`, ♒️.
+
+ 👫 🍵 🔁 **FastAPI** & 🗜 🎻.
+
+## 🚮 🛃 🎚
+
+📤 ⚠ 🌐❔ ⚫️ ⚠ 💪 🚮 🛃 🎚 🇺🇸🔍 ❌. 🖼, 🆎 💂♂.
+
+👆 🎲 🏆 🚫 💪 ⚙️ ⚫️ 🔗 👆 📟.
+
+✋️ 💼 👆 💪 ⚫️ 🏧 😐, 👆 💪 🚮 🛃 🎚:
+
+```Python hl_lines="14"
+{!../../../docs_src/handling_errors/tutorial002.py!}
+```
+
+## ❎ 🛃 ⚠ 🐕🦺
+
+👆 💪 🚮 🛃 ⚠ 🐕🦺 ⏮️ 🎏 ⚠ 🚙 ⚪️➡️ 💃.
+
+➡️ 💬 👆 ✔️ 🛃 ⚠ `UnicornException` 👈 👆 (⚖️ 🗃 👆 ⚙️) 💪 `raise`.
+
+& 👆 💚 🍵 👉 ⚠ 🌐 ⏮️ FastAPI.
+
+👆 💪 🚮 🛃 ⚠ 🐕🦺 ⏮️ `@app.exception_handler()`:
+
+```Python hl_lines="5-7 13-18 24"
+{!../../../docs_src/handling_errors/tutorial003.py!}
+```
+
+📥, 🚥 👆 📨 `/unicorns/yolo`, *➡ 🛠️* 🔜 `raise` `UnicornException`.
+
+✋️ ⚫️ 🔜 🍵 `unicorn_exception_handler`.
+
+, 👆 🔜 📨 🧹 ❌, ⏮️ 🇺🇸🔍 👔 📟 `418` & 🎻 🎚:
+
+```JSON
+{"message": "Oops! yolo did something. There goes a rainbow..."}
+```
+
+!!! note "📡 ℹ"
+ 👆 💪 ⚙️ `from starlette.requests import Request` & `from starlette.responses import JSONResponse`.
+
+ **FastAPI** 🚚 🎏 `starlette.responses` `fastapi.responses` 🏪 👆, 👩💻. ✋️ 🌅 💪 📨 👟 🔗 ⚪️➡️ 💃. 🎏 ⏮️ `Request`.
+
+## 🔐 🔢 ⚠ 🐕🦺
+
+**FastAPI** ✔️ 🔢 ⚠ 🐕🦺.
+
+👫 🐕🦺 🈚 🛬 🔢 🎻 📨 🕐❔ 👆 `raise` `HTTPException` & 🕐❔ 📨 ✔️ ❌ 💽.
+
+👆 💪 🔐 👫 ⚠ 🐕🦺 ⏮️ 👆 👍.
+
+### 🔐 📨 🔬 ⚠
+
+🕐❔ 📨 🔌 ❌ 📊, **FastAPI** 🔘 🤚 `RequestValidationError`.
+
+& ⚫️ 🔌 🔢 ⚠ 🐕🦺 ⚫️.
+
+🔐 ⚫️, 🗄 `RequestValidationError` & ⚙️ ⚫️ ⏮️ `@app.exception_handler(RequestValidationError)` 🎀 ⚠ 🐕🦺.
+
+⚠ 🐕🦺 🔜 📨 `Request` & ⚠.
+
+```Python hl_lines="2 14-16"
+{!../../../docs_src/handling_errors/tutorial004.py!}
+```
+
+🔜, 🚥 👆 🚶 `/items/foo`, ↩️ 💆♂ 🔢 🎻 ❌ ⏮️:
+
+```JSON
+{
+ "detail": [
+ {
+ "loc": [
+ "path",
+ "item_id"
+ ],
+ "msg": "value is not a valid integer",
+ "type": "type_error.integer"
+ }
+ ]
+}
+```
+
+👆 🔜 🤚 ✍ ⏬, ⏮️:
+
+```
+1 validation error
+path -> item_id
+ value is not a valid integer (type=type_error.integer)
+```
+
+#### `RequestValidationError` 🆚 `ValidationError`
+
+!!! warning
+ 👫 📡 ℹ 👈 👆 💪 🚶 🚥 ⚫️ 🚫 ⚠ 👆 🔜.
+
+`RequestValidationError` 🎧-🎓 Pydantic `ValidationError`.
+
+**FastAPI** ⚙️ ⚫️ 👈, 🚥 👆 ⚙️ Pydantic 🏷 `response_model`, & 👆 💽 ✔️ ❌, 👆 🔜 👀 ❌ 👆 🕹.
+
+✋️ 👩💻/👩💻 🔜 🚫 👀 ⚫️. ↩️, 👩💻 🔜 📨 "🔗 💽 ❌" ⏮️ 🇺🇸🔍 👔 📟 `500`.
+
+⚫️ 🔜 👉 🌌 ↩️ 🚥 👆 ✔️ Pydantic `ValidationError` 👆 *📨* ⚖️ 🙆 👆 📟 (🚫 👩💻 *📨*), ⚫️ 🤙 🐛 👆 📟.
+
+& ⏪ 👆 🔧 ⚫️, 👆 👩💻/👩💻 🚫🔜 🚫 ✔️ 🔐 🔗 ℹ 🔃 ❌, 👈 💪 🎦 💂♂ ⚠.
+
+### 🔐 `HTTPException` ❌ 🐕🦺
+
+🎏 🌌, 👆 💪 🔐 `HTTPException` 🐕🦺.
+
+🖼, 👆 💪 💚 📨 ✅ ✍ 📨 ↩️ 🎻 👫 ❌:
+
+```Python hl_lines="3-4 9-11 22"
+{!../../../docs_src/handling_errors/tutorial004.py!}
+```
+
+!!! note "📡 ℹ"
+ 👆 💪 ⚙️ `from starlette.responses import PlainTextResponse`.
+
+ **FastAPI** 🚚 🎏 `starlette.responses` `fastapi.responses` 🏪 👆, 👩💻. ✋️ 🌅 💪 📨 👟 🔗 ⚪️➡️ 💃.
+
+### ⚙️ `RequestValidationError` 💪
+
+`RequestValidationError` 🔌 `body` ⚫️ 📨 ⏮️ ❌ 💽.
+
+👆 💪 ⚙️ ⚫️ ⏪ 🛠️ 👆 📱 🕹 💪 & ℹ ⚫️, 📨 ⚫️ 👩💻, ♒️.
+
+```Python hl_lines="14"
+{!../../../docs_src/handling_errors/tutorial005.py!}
+```
+
+🔜 🔄 📨 ❌ 🏬 💖:
+
+```JSON
+{
+ "title": "towel",
+ "size": "XL"
+}
+```
+
+👆 🔜 📨 📨 💬 👆 👈 💽 ❌ ⚗ 📨 💪:
+
+```JSON hl_lines="12-15"
+{
+ "detail": [
+ {
+ "loc": [
+ "body",
+ "size"
+ ],
+ "msg": "value is not a valid integer",
+ "type": "type_error.integer"
+ }
+ ],
+ "body": {
+ "title": "towel",
+ "size": "XL"
+ }
+}
+```
+
+#### FastAPI `HTTPException` 🆚 💃 `HTTPException`
+
+**FastAPI** ✔️ 🚮 👍 `HTTPException`.
+
+& **FastAPI**'Ⓜ `HTTPException` ❌ 🎓 😖 ⚪️➡️ 💃 `HTTPException` ❌ 🎓.
+
+🕴 🔺, 👈 **FastAPI**'Ⓜ `HTTPException` ✔ 👆 🚮 🎚 🔌 📨.
+
+👉 💪/⚙️ 🔘 ✳ 2️⃣.0️⃣ & 💂♂ 🚙.
+
+, 👆 💪 🚧 🙋♀ **FastAPI**'Ⓜ `HTTPException` 🛎 👆 📟.
+
+✋️ 🕐❔ 👆 ® ⚠ 🐕🦺, 👆 🔜 ® ⚫️ 💃 `HTTPException`.
+
+👉 🌌, 🚥 🙆 🍕 💃 🔗 📟, ⚖️ 💃 ↔ ⚖️ 🔌 -, 🤚 💃 `HTTPException`, 👆 🐕🦺 🔜 💪 ✊ & 🍵 ⚫️.
+
+👉 🖼, 💪 ✔️ 👯♂️ `HTTPException`Ⓜ 🎏 📟, 💃 ⚠ 📁 `StarletteHTTPException`:
+
+```Python
+from starlette.exceptions import HTTPException as StarletteHTTPException
+```
+
+### 🏤-⚙️ **FastAPI**'Ⓜ ⚠ 🐕🦺
+
+🚥 👆 💚 ⚙️ ⚠ ⤴️ ⏮️ 🎏 🔢 ⚠ 🐕🦺 ⚪️➡️ **FastAPI**, 👆 💪 🗄 & 🏤-⚙️ 🔢 ⚠ 🐕🦺 ⚪️➡️ `fastapi.exception_handlers`:
+
+```Python hl_lines="2-5 15 21"
+{!../../../docs_src/handling_errors/tutorial006.py!}
+```
+
+👉 🖼 👆 `print`😅 ❌ ⏮️ 📶 🎨 📧, ✋️ 👆 🤚 💭. 👆 💪 ⚙️ ⚠ & ⤴️ 🏤-⚙️ 🔢 ⚠ 🐕🦺.
diff --git a/docs/em/docs/tutorial/header-params.md b/docs/em/docs/tutorial/header-params.md
new file mode 100644
index 000000000..0f33a1774
--- /dev/null
+++ b/docs/em/docs/tutorial/header-params.md
@@ -0,0 +1,128 @@
+# 🎚 🔢
+
+👆 💪 🔬 🎚 🔢 🎏 🌌 👆 🔬 `Query`, `Path` & `Cookie` 🔢.
+
+## 🗄 `Header`
+
+🥇 🗄 `Header`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/header_params/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/header_params/tutorial001_py310.py!}
+ ```
+
+## 📣 `Header` 🔢
+
+⤴️ 📣 🎚 🔢 ⚙️ 🎏 📊 ⏮️ `Path`, `Query` & `Cookie`.
+
+🥇 💲 🔢 💲, 👆 💪 🚶♀️ 🌐 ➕ 🔬 ⚖️ ✍ 🔢:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/header_params/tutorial001_py310.py!}
+ ```
+
+!!! note "📡 ℹ"
+ `Header` "👭" 🎓 `Path`, `Query` & `Cookie`. ⚫️ 😖 ⚪️➡️ 🎏 ⚠ `Param` 🎓.
+
+ ✋️ 💭 👈 🕐❔ 👆 🗄 `Query`, `Path`, `Header`, & 🎏 ⚪️➡️ `fastapi`, 👈 🤙 🔢 👈 📨 🎁 🎓.
+
+!!! info
+ 📣 🎚, 👆 💪 ⚙️ `Header`, ↩️ ⏪ 🔢 🔜 🔬 🔢 🔢.
+
+## 🏧 🛠️
+
+`Header` ✔️ 🐥 ➕ 🛠️ 🔛 🔝 ⚫️❔ `Path`, `Query` & `Cookie` 🚚.
+
+🌅 🐩 🎚 🎏 "🔠" 🦹, 💭 "➖ 🔣" (`-`).
+
+✋️ 🔢 💖 `user-agent` ❌ 🐍.
+
+, 🔢, `Header` 🔜 🗜 🔢 📛 🦹 ⚪️➡️ 🎦 (`_`) 🔠 (`-`) ⚗ & 📄 🎚.
+
+, 🇺🇸🔍 🎚 💼-😛,, 👆 💪 📣 👫 ⏮️ 🐩 🐍 👗 (💭 "🔡").
+
+, 👆 💪 ⚙️ `user_agent` 👆 🛎 🔜 🐍 📟, ↩️ 💆♂ 🎯 🥇 🔤 `User_Agent` ⚖️ 🕳 🎏.
+
+🚥 🤔 👆 💪 ❎ 🏧 🛠️ 🎦 🔠, ⚒ 🔢 `convert_underscores` `Header` `False`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/header_params/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/header_params/tutorial002_py310.py!}
+ ```
+
+!!! warning
+ ⏭ ⚒ `convert_underscores` `False`, 🐻 🤯 👈 🇺🇸🔍 🗳 & 💽 / ⚙️ 🎚 ⏮️ 🎦.
+
+## ❎ 🎚
+
+⚫️ 💪 📨 ❎ 🎚. 👈 ⛓, 🎏 🎚 ⏮️ 💗 💲.
+
+👆 💪 🔬 👈 💼 ⚙️ 📇 🆎 📄.
+
+👆 🔜 📨 🌐 💲 ⚪️➡️ ❎ 🎚 🐍 `list`.
+
+🖼, 📣 🎚 `X-Token` 👈 💪 😑 🌅 🌘 🕐, 👆 💪 ✍:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial003_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/header_params/tutorial003_py310.py!}
+ ```
+
+🚥 👆 🔗 ⏮️ 👈 *➡ 🛠️* 📨 2️⃣ 🇺🇸🔍 🎚 💖:
+
+```
+X-Token: foo
+X-Token: bar
+```
+
+📨 🔜 💖:
+
+```JSON
+{
+ "X-Token values": [
+ "bar",
+ "foo"
+ ]
+}
+```
+
+## 🌃
+
+📣 🎚 ⏮️ `Header`, ⚙️ 🎏 ⚠ ⚓ `Query`, `Path` & `Cookie`.
+
+& 🚫 😟 🔃 🎦 👆 🔢, **FastAPI** 🔜 ✊ 💅 🏭 👫.
diff --git a/docs/em/docs/tutorial/index.md b/docs/em/docs/tutorial/index.md
new file mode 100644
index 000000000..8536dc3ee
--- /dev/null
+++ b/docs/em/docs/tutorial/index.md
@@ -0,0 +1,80 @@
+# 🔰 - 👩💻 🦮 - 🎶
+
+👉 🔰 🎦 👆 ❔ ⚙️ **FastAPI** ⏮️ 🌅 🚮 ⚒, 🔁 🔁.
+
+🔠 📄 📉 🏗 🔛 ⏮️ 🕐, ✋️ ⚫️ 🏗 🎏 ❔, 👈 👆 💪 🚶 🔗 🙆 🎯 1️⃣ ❎ 👆 🎯 🛠️ 💪.
+
+⚫️ 🏗 👷 🔮 🔗.
+
+👆 💪 👟 🔙 & 👀 ⚫️❔ ⚫️❔ 👆 💪.
+
+## 🏃 📟
+
+🌐 📟 🍫 💪 📁 & ⚙️ 🔗 (👫 🤙 💯 🐍 📁).
+
+🏃 🙆 🖼, 📁 📟 📁 `main.py`, & ▶️ `uvicorn` ⏮️:
+
+contact 🏑| 🔢 | 🆎 | 📛 |
|---|---|---|
name | str | ⚖ 📛 📧 👨💼/🏢. |
url | str | 📛 ☝ 📧 ℹ. 🔜 📁 📛. |
email | str | 📧 📢 📧 👨💼/🏢. 🔜 📁 📧 📢. |
license_info 🏑| 🔢 | 🆎 | 📛 |
|---|---|---|
name | str | 🚚 (🚥 license_info ⚒). 🛂 📛 ⚙️ 🛠️. |
url | str | 📛 🛂 ⚙️ 🛠️. 🔜 📁 📛. |
+
+## 🗃 🔖
+
+👆 💪 🚮 🌖 🗃 🎏 🔖 ⚙️ 👪 👆 ➡ 🛠️ ⏮️ 🔢 `openapi_tags`.
+
+⚫️ ✊ 📇 ⚗ 1️⃣ 📖 🔠 🔖.
+
+🔠 📖 💪 🔌:
+
+* `name` (**✔**): `str` ⏮️ 🎏 📛 👆 ⚙️ `tags` 🔢 👆 *➡ 🛠️* & `APIRouter`Ⓜ.
+* `description`: `str` ⏮️ 📏 📛 🔖. ⚫️ 💪 ✔️ ✍ & 🔜 🎦 🩺 🎚.
+* `externalDocs`: `dict` 🔬 🔢 🧾 ⏮️:
+ * `description`: `str` ⏮️ 📏 📛 🔢 🩺.
+ * `url` (**✔**): `str` ⏮️ 📛 🔢 🧾.
+
+### ✍ 🗃 🔖
+
+➡️ 🔄 👈 🖼 ⏮️ 🔖 `users` & `items`.
+
+✍ 🗃 👆 🔖 & 🚶♀️ ⚫️ `openapi_tags` 🔢:
+
+```Python hl_lines="3-16 18"
+{!../../../docs_src/metadata/tutorial004.py!}
+```
+
+👀 👈 👆 💪 ⚙️ ✍ 🔘 📛, 🖼 "💳" 🔜 🎦 🦁 (**💳**) & "🎀" 🔜 🎦 ❕ (_🎀_).
+
+!!! tip
+ 👆 🚫 ✔️ 🚮 🗃 🌐 🔖 👈 👆 ⚙️.
+
+### ⚙️ 👆 🔖
+
+⚙️ `tags` 🔢 ⏮️ 👆 *➡ 🛠️* (& `APIRouter`Ⓜ) 🛠️ 👫 🎏 🔖:
+
+```Python hl_lines="21 26"
+{!../../../docs_src/metadata/tutorial004.py!}
+```
+
+!!! info
+ ✍ 🌅 🔃 🔖 [➡ 🛠️ 📳](../path-operation-configuration/#tags){.internal-link target=_blank}.
+
+### ✅ 🩺
+
+🔜, 🚥 👆 ✅ 🩺, 👫 🔜 🎦 🌐 🌖 🗃:
+
+
+
+### ✔ 🔖
+
+✔ 🔠 🔖 🗃 📖 🔬 ✔ 🎦 🩺 🎚.
+
+🖼, ✋️ `users` 🔜 🚶 ⏮️ `items` 🔤 ✔, ⚫️ 🎦 ⏭ 👫, ↩️ 👥 🚮 👫 🗃 🥇 📖 📇.
+
+## 🗄 📛
+
+🔢, 🗄 🔗 🍦 `/openapi.json`.
+
+✋️ 👆 💪 🔗 ⚫️ ⏮️ 🔢 `openapi_url`.
+
+🖼, ⚒ ⚫️ 🍦 `/api/v1/openapi.json`:
+
+```Python hl_lines="3"
+{!../../../docs_src/metadata/tutorial002.py!}
+```
+
+🚥 👆 💚 ❎ 🗄 🔗 🍕 👆 💪 ⚒ `openapi_url=None`, 👈 🔜 ❎ 🧾 👩💻 🔢 👈 ⚙️ ⚫️.
+
+## 🩺 📛
+
+👆 💪 🔗 2️⃣ 🧾 👩💻 🔢 🔌:
+
+* **🦁 🎚**: 🍦 `/docs`.
+ * 👆 💪 ⚒ 🚮 📛 ⏮️ 🔢 `docs_url`.
+ * 👆 💪 ❎ ⚫️ ⚒ `docs_url=None`.
+* **📄**: 🍦 `/redoc`.
+ * 👆 💪 ⚒ 🚮 📛 ⏮️ 🔢 `redoc_url`.
+ * 👆 💪 ❎ ⚫️ ⚒ `redoc_url=None`.
+
+🖼, ⚒ 🦁 🎚 🍦 `/documentation` & ❎ 📄:
+
+```Python hl_lines="3"
+{!../../../docs_src/metadata/tutorial003.py!}
+```
diff --git a/docs/em/docs/tutorial/middleware.md b/docs/em/docs/tutorial/middleware.md
new file mode 100644
index 000000000..644b4690c
--- /dev/null
+++ b/docs/em/docs/tutorial/middleware.md
@@ -0,0 +1,61 @@
+# 🛠️
+
+👆 💪 🚮 🛠️ **FastAPI** 🈸.
+
+"🛠️" 🔢 👈 👷 ⏮️ 🔠 **📨** ⏭ ⚫️ 🛠️ 🙆 🎯 *➡ 🛠️*. & ⏮️ 🔠 **📨** ⏭ 🛬 ⚫️.
+
+* ⚫️ ✊ 🔠 **📨** 👈 👟 👆 🈸.
+* ⚫️ 💪 ⤴️ 🕳 👈 **📨** ⚖️ 🏃 🙆 💪 📟.
+* ⤴️ ⚫️ 🚶♀️ **📨** 🛠️ 🎂 🈸 ( *➡ 🛠️*).
+* ⚫️ ⤴️ ✊ **📨** 🏗 🈸 ( *➡ 🛠️*).
+* ⚫️ 💪 🕳 👈 **📨** ⚖️ 🏃 🙆 💪 📟.
+* ⤴️ ⚫️ 📨 **📨**.
+
+!!! note "📡 ℹ"
+ 🚥 👆 ✔️ 🔗 ⏮️ `yield`, 🚪 📟 🔜 🏃 *⏮️* 🛠️.
+
+ 🚥 📤 🙆 🖥 📋 (📄 ⏪), 👫 🔜 🏃 *⏮️* 🌐 🛠️.
+
+## ✍ 🛠️
+
+✍ 🛠️ 👆 ⚙️ 👨🎨 `@app.middleware("http")` 🔛 🔝 🔢.
+
+🛠️ 🔢 📨:
+
+* `request`.
+* 🔢 `call_next` 👈 🔜 📨 `request` 🔢.
+ * 👉 🔢 🔜 🚶♀️ `request` 🔗 *➡ 🛠️*.
+ * ⤴️ ⚫️ 📨 `response` 🏗 🔗 *➡ 🛠️*.
+* 👆 💪 ⤴️ 🔀 🌅 `response` ⏭ 🛬 ⚫️.
+
+```Python hl_lines="8-9 11 14"
+{!../../../docs_src/middleware/tutorial001.py!}
+```
+
+!!! tip
+ ✔️ 🤯 👈 🛃 © 🎚 💪 🚮 ⚙️ '✖-' 🔡.
+
+ ✋️ 🚥 👆 ✔️ 🛃 🎚 👈 👆 💚 👩💻 🖥 💪 👀, 👆 💪 🚮 👫 👆 ⚜ 📳 ([⚜ (✖️-🇨🇳 ℹ 🤝)](cors.md){.internal-link target=_blank}) ⚙️ 🔢 `expose_headers` 📄 💃 ⚜ 🩺.
+
+!!! note "📡 ℹ"
+ 👆 💪 ⚙️ `from starlette.requests import Request`.
+
+ **FastAPI** 🚚 ⚫️ 🏪 👆, 👩💻. ✋️ ⚫️ 👟 🔗 ⚪️➡️ 💃.
+
+### ⏭ & ⏮️ `response`
+
+👆 💪 🚮 📟 🏃 ⏮️ `request`, ⏭ 🙆 *➡ 🛠️* 📨 ⚫️.
+
+& ⏮️ `response` 🏗, ⏭ 🛬 ⚫️.
+
+🖼, 👆 💪 🚮 🛃 🎚 `X-Process-Time` ⚗ 🕰 🥈 👈 ⚫️ ✊ 🛠️ 📨 & 🏗 📨:
+
+```Python hl_lines="10 12-13"
+{!../../../docs_src/middleware/tutorial001.py!}
+```
+
+## 🎏 🛠️
+
+👆 💪 ⏪ ✍ 🌖 🔃 🎏 🛠️ [🏧 👩💻 🦮: 🏧 🛠️](../advanced/middleware.md){.internal-link target=_blank}.
+
+👆 🔜 ✍ 🔃 ❔ 🍵 ⚜ ⏮️ 🛠️ ⏭ 📄.
diff --git a/docs/em/docs/tutorial/path-operation-configuration.md b/docs/em/docs/tutorial/path-operation-configuration.md
new file mode 100644
index 000000000..916529258
--- /dev/null
+++ b/docs/em/docs/tutorial/path-operation-configuration.md
@@ -0,0 +1,179 @@
+# ➡ 🛠️ 📳
+
+📤 📚 🔢 👈 👆 💪 🚶♀️ 👆 *➡ 🛠️ 👨🎨* 🔗 ⚫️.
+
+!!! warning
+ 👀 👈 👫 🔢 🚶♀️ 🔗 *➡ 🛠️ 👨🎨*, 🚫 👆 *➡ 🛠️ 🔢*.
+
+## 📨 👔 📟
+
+👆 💪 🔬 (🇺🇸🔍) `status_code` ⚙️ 📨 👆 *➡ 🛠️*.
+
+👆 💪 🚶♀️ 🔗 `int` 📟, 💖 `404`.
+
+✋️ 🚥 👆 🚫 💭 ⚫️❔ 🔠 🔢 📟, 👆 💪 ⚙️ ⌨ 📉 `status`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="3 17"
+ {!> ../../../docs_src/path_operation_configuration/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="3 17"
+ {!> ../../../docs_src/path_operation_configuration/tutorial001_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="1 15"
+ {!> ../../../docs_src/path_operation_configuration/tutorial001_py310.py!}
+ ```
+
+👈 👔 📟 🔜 ⚙️ 📨 & 🔜 🚮 🗄 🔗.
+
+!!! note "📡 ℹ"
+ 👆 💪 ⚙️ `from starlette import status`.
+
+ **FastAPI** 🚚 🎏 `starlette.status` `fastapi.status` 🏪 👆, 👩💻. ✋️ ⚫️ 👟 🔗 ⚪️➡️ 💃.
+
+## 🔖
+
+👆 💪 🚮 🔖 👆 *➡ 🛠️*, 🚶♀️ 🔢 `tags` ⏮️ `list` `str` (🛎 1️⃣ `str`):
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="17 22 27"
+ {!> ../../../docs_src/path_operation_configuration/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="17 22 27"
+ {!> ../../../docs_src/path_operation_configuration/tutorial002_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="15 20 25"
+ {!> ../../../docs_src/path_operation_configuration/tutorial002_py310.py!}
+ ```
+
+👫 🔜 🚮 🗄 🔗 & ⚙️ 🏧 🧾 🔢:
+
+
+
+### 🔖 ⏮️ 🔢
+
+🚥 👆 ✔️ 🦏 🈸, 👆 5️⃣📆 🔚 🆙 📈 **📚 🔖**, & 👆 🔜 💚 ⚒ 💭 👆 🕧 ⚙️ **🎏 🔖** 🔗 *➡ 🛠️*.
+
+👫 💼, ⚫️ 💪 ⚒ 🔑 🏪 🔖 `Enum`.
+
+**FastAPI** 🐕🦺 👈 🎏 🌌 ⏮️ ✅ 🎻:
+
+```Python hl_lines="1 8-10 13 18"
+{!../../../docs_src/path_operation_configuration/tutorial002b.py!}
+```
+
+## 📄 & 📛
+
+👆 💪 🚮 `summary` & `description`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="20-21"
+ {!> ../../../docs_src/path_operation_configuration/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="20-21"
+ {!> ../../../docs_src/path_operation_configuration/tutorial003_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="18-19"
+ {!> ../../../docs_src/path_operation_configuration/tutorial003_py310.py!}
+ ```
+
+## 📛 ⚪️➡️ #️⃣
+
+📛 😑 📏 & 📔 💗 ⏸, 👆 💪 📣 *➡ 🛠️* 📛 🔢 #️⃣ & **FastAPI** 🔜 ✍ ⚫️ ⚪️➡️ 📤.
+
+👆 💪 ✍ ✍ #️⃣ , ⚫️ 🔜 🔬 & 🖥 ☑ (✊ 🔘 🏧 #️⃣ 📐).
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="19-27"
+ {!> ../../../docs_src/path_operation_configuration/tutorial004.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="19-27"
+ {!> ../../../docs_src/path_operation_configuration/tutorial004_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="17-25"
+ {!> ../../../docs_src/path_operation_configuration/tutorial004_py310.py!}
+ ```
+
+⚫️ 🔜 ⚙️ 🎓 🩺:
+
+
+
+## 📨 📛
+
+👆 💪 ✔ 📨 📛 ⏮️ 🔢 `response_description`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="21"
+ {!> ../../../docs_src/path_operation_configuration/tutorial005.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="21"
+ {!> ../../../docs_src/path_operation_configuration/tutorial005_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/path_operation_configuration/tutorial005_py310.py!}
+ ```
+
+!!! info
+ 👀 👈 `response_description` 🔗 🎯 📨, `description` 🔗 *➡ 🛠️* 🏢.
+
+!!! check
+ 🗄 ✔ 👈 🔠 *➡ 🛠️* 🚚 📨 📛.
+
+ , 🚥 👆 🚫 🚚 1️⃣, **FastAPI** 🔜 🔁 🏗 1️⃣ "🏆 📨".
+
+
+
+## 😢 *➡ 🛠️*
+
+🚥 👆 💪 ™ *➡ 🛠️* 😢, ✋️ 🍵 ❎ ⚫️, 🚶♀️ 🔢 `deprecated`:
+
+```Python hl_lines="16"
+{!../../../docs_src/path_operation_configuration/tutorial006.py!}
+```
+
+⚫️ 🔜 🎯 ™ 😢 🎓 🩺:
+
+
+
+✅ ❔ 😢 & 🚫-😢 *➡ 🛠️* 👀 💖:
+
+
+
+## 🌃
+
+👆 💪 🔗 & 🚮 🗃 👆 *➡ 🛠️* 💪 🚶♀️ 🔢 *➡ 🛠️ 👨🎨*.
diff --git a/docs/em/docs/tutorial/path-params-numeric-validations.md b/docs/em/docs/tutorial/path-params-numeric-validations.md
new file mode 100644
index 000000000..b1ba2670b
--- /dev/null
+++ b/docs/em/docs/tutorial/path-params-numeric-validations.md
@@ -0,0 +1,138 @@
+# ➡ 🔢 & 🔢 🔬
+
+🎏 🌌 👈 👆 💪 📣 🌅 🔬 & 🗃 🔢 🔢 ⏮️ `Query`, 👆 💪 📣 🎏 🆎 🔬 & 🗃 ➡ 🔢 ⏮️ `Path`.
+
+## 🗄 ➡
+
+🥇, 🗄 `Path` ⚪️➡️ `fastapi`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
+ ```
+
+## 📣 🗃
+
+👆 💪 📣 🌐 🎏 🔢 `Query`.
+
+🖼, 📣 `title` 🗃 💲 ➡ 🔢 `item_id` 👆 💪 🆎:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
+ ```
+
+!!! note
+ ➡ 🔢 🕧 ✔ ⚫️ ✔️ 🍕 ➡.
+
+ , 👆 🔜 📣 ⚫️ ⏮️ `...` ™ ⚫️ ✔.
+
+ 👐, 🚥 👆 📣 ⚫️ ⏮️ `None` ⚖️ ⚒ 🔢 💲, ⚫️ 🔜 🚫 📉 🕳, ⚫️ 🔜 🕧 🚚.
+
+## ✔ 🔢 👆 💪
+
+➡️ 💬 👈 👆 💚 📣 🔢 🔢 `q` ✔ `str`.
+
+& 👆 🚫 💪 📣 🕳 🙆 👈 🔢, 👆 🚫 🤙 💪 ⚙️ `Query`.
+
+✋️ 👆 💪 ⚙️ `Path` `item_id` ➡ 🔢.
+
+🐍 🔜 😭 🚥 👆 🚮 💲 ⏮️ "🔢" ⏭ 💲 👈 🚫 ✔️ "🔢".
+
+✋️ 👆 💪 🏤-✔ 👫, & ✔️ 💲 🍵 🔢 (🔢 🔢 `q`) 🥇.
+
+⚫️ 🚫 🤔 **FastAPI**. ⚫️ 🔜 🔍 🔢 👫 📛, 🆎 & 🔢 📄 (`Query`, `Path`, ♒️), ⚫️ 🚫 💅 🔃 ✔.
+
+, 👆 💪 📣 👆 🔢:
+
+```Python hl_lines="7"
+{!../../../docs_src/path_params_numeric_validations/tutorial002.py!}
+```
+
+## ✔ 🔢 👆 💪, 🎱
+
+🚥 👆 💚 📣 `q` 🔢 🔢 🍵 `Query` 🚫 🙆 🔢 💲, & ➡ 🔢 `item_id` ⚙️ `Path`, & ✔️ 👫 🎏 ✔, 🐍 ✔️ 🐥 🎁 ❕ 👈.
+
+🚶♀️ `*`, 🥇 🔢 🔢.
+
+🐍 🏆 🚫 🕳 ⏮️ 👈 `*`, ✋️ ⚫️ 🔜 💭 👈 🌐 📄 🔢 🔜 🤙 🇨🇻 ❌ (🔑-💲 👫), 💭 kwargs. 🚥 👫 🚫 ✔️ 🔢 💲.
+
+```Python hl_lines="7"
+{!../../../docs_src/path_params_numeric_validations/tutorial003.py!}
+```
+
+## 🔢 🔬: 👑 🌘 ⚖️ 🌓
+
+⏮️ `Query` & `Path` (& 🎏 👆 🔜 👀 ⏪) 👆 💪 📣 🔢 ⚛.
+
+📥, ⏮️ `ge=1`, `item_id` 🔜 💪 🔢 🔢 "`g`🅾 🌘 ⚖️ `e`🅾" `1`.
+
+```Python hl_lines="8"
+{!../../../docs_src/path_params_numeric_validations/tutorial004.py!}
+```
+
+## 🔢 🔬: 🌘 🌘 & 🌘 🌘 ⚖️ 🌓
+
+🎏 ✔:
+
+* `gt`: `g`🅾 `t`👲
+* `le`: `l`👭 🌘 ⚖️ `e`🅾
+
+```Python hl_lines="9"
+{!../../../docs_src/path_params_numeric_validations/tutorial005.py!}
+```
+
+## 🔢 🔬: 🎈, 🌘 🌘 & 🌘 🌘
+
+🔢 🔬 👷 `float` 💲.
+
+📥 🌐❔ ⚫️ ▶️️ ⚠ 💪 📣 gt & 🚫 ge. ⏮️ ⚫️ 👆 💪 🚚, 🖼, 👈 💲 🔜 👑 🌘 `0`, 🚥 ⚫️ 🌘 🌘 `1`.
+
+, `0.5` 🔜 ☑ 💲. ✋️ `0.0` ⚖️ `0` 🔜 🚫.
+
+& 🎏 lt.
+
+```Python hl_lines="11"
+{!../../../docs_src/path_params_numeric_validations/tutorial006.py!}
+```
+
+## 🌃
+
+⏮️ `Query`, `Path` (& 🎏 👆 🚫 👀) 👆 💪 📣 🗃 & 🎻 🔬 🎏 🌌 ⏮️ [🔢 🔢 & 🎻 🔬](query-params-str-validations.md){.internal-link target=_blank}.
+
+& 👆 💪 📣 🔢 🔬:
+
+* `gt`: `g`🅾 `t`👲
+* `ge`: `g`🅾 🌘 ⚖️ `e`🅾
+* `lt`: `l`👭 `t`👲
+* `le`: `l`👭 🌘 ⚖️ `e`🅾
+
+!!! info
+ `Query`, `Path`, & 🎏 🎓 👆 🔜 👀 ⏪ 🏿 ⚠ `Param` 🎓.
+
+ 🌐 👫 💰 🎏 🔢 🌖 🔬 & 🗃 👆 ✔️ 👀.
+
+!!! note "📡 ℹ"
+ 🕐❔ 👆 🗄 `Query`, `Path` & 🎏 ⚪️➡️ `fastapi`, 👫 🤙 🔢.
+
+ 👈 🕐❔ 🤙, 📨 👐 🎓 🎏 📛.
+
+ , 👆 🗄 `Query`, ❔ 🔢. & 🕐❔ 👆 🤙 ⚫️, ⚫️ 📨 👐 🎓 🌟 `Query`.
+
+ 👫 🔢 📤 (↩️ ⚙️ 🎓 🔗) 👈 👆 👨🎨 🚫 ™ ❌ 🔃 👫 🆎.
+
+ 👈 🌌 👆 💪 ⚙️ 👆 😐 👨🎨 & 🛠️ 🧰 🍵 ✔️ 🚮 🛃 📳 🤷♂ 📚 ❌.
diff --git a/docs/em/docs/tutorial/path-params.md b/docs/em/docs/tutorial/path-params.md
new file mode 100644
index 000000000..ea939b458
--- /dev/null
+++ b/docs/em/docs/tutorial/path-params.md
@@ -0,0 +1,252 @@
+# ➡ 🔢
+
+👆 💪 📣 ➡ "🔢" ⚖️ "🔢" ⏮️ 🎏 ❕ ⚙️ 🐍 📁 🎻:
+
+```Python hl_lines="6-7"
+{!../../../docs_src/path_params/tutorial001.py!}
+```
+
+💲 ➡ 🔢 `item_id` 🔜 🚶♀️ 👆 🔢 ❌ `item_id`.
+
+, 🚥 👆 🏃 👉 🖼 & 🚶 http://127.0.0.1:8000/items/foo, 👆 🔜 👀 📨:
+
+```JSON
+{"item_id":"foo"}
+```
+
+## ➡ 🔢 ⏮️ 🆎
+
+👆 💪 📣 🆎 ➡ 🔢 🔢, ⚙️ 🐩 🐍 🆎 ✍:
+
+```Python hl_lines="7"
+{!../../../docs_src/path_params/tutorial002.py!}
+```
+
+👉 💼, `item_id` 📣 `int`.
+
+!!! check
+ 👉 🔜 🤝 👆 👨🎨 🐕🦺 🔘 👆 🔢, ⏮️ ❌ ✅, 🛠️, ♒️.
+
+## 💽 🛠️
+
+🚥 👆 🏃 👉 🖼 & 📂 👆 🖥 http://127.0.0.1:8000/items/3, 👆 🔜 👀 📨:
+
+```JSON
+{"item_id":3}
+```
+
+!!! check
+ 👀 👈 💲 👆 🔢 📨 (& 📨) `3`, 🐍 `int`, 🚫 🎻 `"3"`.
+
+ , ⏮️ 👈 🆎 📄, **FastAPI** 🤝 👆 🏧 📨 "✍".
+
+## 💽 🔬
+
+✋️ 🚥 👆 🚶 🖥 http://127.0.0.1:8000/items/foo, 👆 🔜 👀 👌 🇺🇸🔍 ❌:
+
+```JSON
+{
+ "detail": [
+ {
+ "loc": [
+ "path",
+ "item_id"
+ ],
+ "msg": "value is not a valid integer",
+ "type": "type_error.integer"
+ }
+ ]
+}
+```
+
+↩️ ➡ 🔢 `item_id` ✔️ 💲 `"foo"`, ❔ 🚫 `int`.
+
+🎏 ❌ 🔜 😑 🚥 👆 🚚 `float` ↩️ `int`,: http://127.0.0.1:8000/items/4.2
+
+!!! check
+ , ⏮️ 🎏 🐍 🆎 📄, **FastAPI** 🤝 👆 💽 🔬.
+
+ 👀 👈 ❌ 🎯 🇵🇸 ⚫️❔ ☝ 🌐❔ 🔬 🚫 🚶♀️.
+
+ 👉 🙃 👍 ⏪ 🛠️ & 🛠️ 📟 👈 🔗 ⏮️ 👆 🛠️.
+
+## 🧾
+
+& 🕐❔ 👆 📂 👆 🖥 http://127.0.0.1:8000/docs, 👆 🔜 👀 🏧, 🎓, 🛠️ 🧾 💖:
+
+
+
+!!! check
+ 🔄, ⏮️ 👈 🎏 🐍 🆎 📄, **FastAPI** 🤝 👆 🏧, 🎓 🧾 (🛠️ 🦁 🎚).
+
+ 👀 👈 ➡ 🔢 📣 🔢.
+
+## 🐩-⚓️ 💰, 🎛 🧾
+
+& ↩️ 🏗 🔗 ⚪️➡️ 🗄 🐩, 📤 📚 🔗 🧰.
+
+↩️ 👉, **FastAPI** ⚫️ 🚚 🎛 🛠️ 🧾 (⚙️ 📄), ❔ 👆 💪 🔐 http://127.0.0.1:8000/redoc:
+
+
+
+🎏 🌌, 📤 📚 🔗 🧰. ✅ 📟 ⚡ 🧰 📚 🇪🇸.
+
+## Pydantic
+
+🌐 💽 🔬 🎭 🔽 🚘 Pydantic, 👆 🤚 🌐 💰 ⚪️➡️ ⚫️. & 👆 💭 👆 👍 ✋.
+
+👆 💪 ⚙️ 🎏 🆎 📄 ⏮️ `str`, `float`, `bool` & 📚 🎏 🏗 📊 🆎.
+
+📚 👫 🔬 ⏭ 📃 🔰.
+
+## ✔ 🤔
+
+🕐❔ 🏗 *➡ 🛠️*, 👆 💪 🔎 ⚠ 🌐❔ 👆 ✔️ 🔧 ➡.
+
+💖 `/users/me`, ➡️ 💬 👈 ⚫️ 🤚 📊 🔃 ⏮️ 👩💻.
+
+& ⤴️ 👆 💪 ✔️ ➡ `/users/{user_id}` 🤚 💽 🔃 🎯 👩💻 👩💻 🆔.
+
+↩️ *➡ 🛠️* 🔬 ✔, 👆 💪 ⚒ 💭 👈 ➡ `/users/me` 📣 ⏭ 1️⃣ `/users/{user_id}`:
+
+```Python hl_lines="6 11"
+{!../../../docs_src/path_params/tutorial003.py!}
+```
+
+⏪, ➡ `/users/{user_id}` 🔜 🏏 `/users/me`, "💭" 👈 ⚫️ 📨 🔢 `user_id` ⏮️ 💲 `"me"`.
+
+➡, 👆 🚫🔜 ↔ ➡ 🛠️:
+
+```Python hl_lines="6 11"
+{!../../../docs_src/path_params/tutorial003b.py!}
+```
+
+🥇 🕐 🔜 🕧 ⚙️ ↩️ ➡ 🏏 🥇.
+
+## 🔁 💲
+
+🚥 👆 ✔️ *➡ 🛠️* 👈 📨 *➡ 🔢*, ✋️ 👆 💚 💪 ☑ *➡ 🔢* 💲 🔁, 👆 💪 ⚙️ 🐩 🐍 `Enum`.
+
+### ✍ `Enum` 🎓
+
+🗄 `Enum` & ✍ 🎧-🎓 👈 😖 ⚪️➡️ `str` & ⚪️➡️ `Enum`.
+
+😖 ⚪️➡️ `str` 🛠️ 🩺 🔜 💪 💭 👈 💲 🔜 🆎 `string` & 🔜 💪 ✍ ☑.
+
+⤴️ ✍ 🎓 🔢 ⏮️ 🔧 💲, ❔ 🔜 💪 ☑ 💲:
+
+```Python hl_lines="1 6-9"
+{!../../../docs_src/path_params/tutorial005.py!}
+```
+
+!!! info
+ 🔢 (⚖️ 🔢) 💪 🐍 ↩️ ⏬ 3️⃣.4️⃣.
+
+!!! tip
+ 🚥 👆 💭, "📊", "🎓", & "🍏" 📛 🎰 🏫 🏷.
+
+### 📣 *➡ 🔢*
+
+⤴️ ✍ *➡ 🔢* ⏮️ 🆎 ✍ ⚙️ 🔢 🎓 👆 ✍ (`ModelName`):
+
+```Python hl_lines="16"
+{!../../../docs_src/path_params/tutorial005.py!}
+```
+
+### ✅ 🩺
+
+↩️ 💪 💲 *➡ 🔢* 🔢, 🎓 🩺 💪 🎦 👫 🎆:
+
+
+
+### 👷 ⏮️ 🐍 *🔢*
+
+💲 *➡ 🔢* 🔜 *🔢 👨🎓*.
+
+#### 🔬 *🔢 👨🎓*
+
+👆 💪 🔬 ⚫️ ⏮️ *🔢 👨🎓* 👆 ✍ 🔢 `ModelName`:
+
+```Python hl_lines="17"
+{!../../../docs_src/path_params/tutorial005.py!}
+```
+
+#### 🤚 *🔢 💲*
+
+👆 💪 🤚 ☑ 💲 ( `str` 👉 💼) ⚙️ `model_name.value`, ⚖️ 🏢, `your_enum_member.value`:
+
+```Python hl_lines="20"
+{!../../../docs_src/path_params/tutorial005.py!}
+```
+
+!!! tip
+ 👆 💪 🔐 💲 `"lenet"` ⏮️ `ModelName.lenet.value`.
+
+#### 📨 *🔢 👨🎓*
+
+👆 💪 📨 *🔢 👨🎓* ⚪️➡️ 👆 *➡ 🛠️*, 🐦 🎻 💪 (✅ `dict`).
+
+👫 🔜 🗜 👫 🔗 💲 (🎻 👉 💼) ⏭ 🛬 👫 👩💻:
+
+```Python hl_lines="18 21 23"
+{!../../../docs_src/path_params/tutorial005.py!}
+```
+
+👆 👩💻 👆 🔜 🤚 🎻 📨 💖:
+
+```JSON
+{
+ "model_name": "alexnet",
+ "message": "Deep Learning FTW!"
+}
+```
+
+## ➡ 🔢 ⚗ ➡
+
+➡️ 💬 👆 ✔️ *➡ 🛠️* ⏮️ ➡ `/files/{file_path}`.
+
+✋️ 👆 💪 `file_path` ⚫️ 🔌 *➡*, 💖 `home/johndoe/myfile.txt`.
+
+, 📛 👈 📁 🔜 🕳 💖: `/files/home/johndoe/myfile.txt`.
+
+### 🗄 🐕🦺
+
+🗄 🚫 🐕🦺 🌌 📣 *➡ 🔢* 🔌 *➡* 🔘, 👈 💪 ↘️ 😐 👈 ⚠ 💯 & 🔬.
+
+👐, 👆 💪 ⚫️ **FastAPI**, ⚙️ 1️⃣ 🔗 🧰 ⚪️➡️ 💃.
+
+& 🩺 🔜 👷, 👐 🚫 ❎ 🙆 🧾 💬 👈 🔢 🔜 🔌 ➡.
+
+### ➡ 🔌
+
+⚙️ 🎛 🔗 ⚪️➡️ 💃 👆 💪 📣 *➡ 🔢* ⚗ *➡* ⚙️ 📛 💖:
+
+```
+/files/{file_path:path}
+```
+
+👉 💼, 📛 🔢 `file_path`, & 🏁 🍕, `:path`, 💬 ⚫️ 👈 🔢 🔜 🏏 🙆 *➡*.
+
+, 👆 💪 ⚙️ ⚫️ ⏮️:
+
+```Python hl_lines="6"
+{!../../../docs_src/path_params/tutorial004.py!}
+```
+
+!!! tip
+ 👆 💪 💪 🔢 🔌 `/home/johndoe/myfile.txt`, ⏮️ 🏁 🔪 (`/`).
+
+ 👈 💼, 📛 🔜: `/files//home/johndoe/myfile.txt`, ⏮️ 2️⃣✖️ 🔪 (`//`) 🖖 `files` & `home`.
+
+## 🌃
+
+⏮️ **FastAPI**, ⚙️ 📏, 🏋️ & 🐩 🐍 🆎 📄, 👆 🤚:
+
+* 👨🎨 🐕🦺: ❌ ✅, ✍, ♒️.
+* 💽 "✍"
+* 💽 🔬
+* 🛠️ ✍ & 🏧 🧾
+
+& 👆 🕴 ✔️ 📣 👫 🕐.
+
+👈 🎲 👑 ⭐ 📈 **FastAPI** 🔬 🎛 🛠️ (↖️ ⚪️➡️ 🍣 🎭).
diff --git a/docs/em/docs/tutorial/query-params-str-validations.md b/docs/em/docs/tutorial/query-params-str-validations.md
new file mode 100644
index 000000000..d6b67bd51
--- /dev/null
+++ b/docs/em/docs/tutorial/query-params-str-validations.md
@@ -0,0 +1,467 @@
+# 🔢 🔢 & 🎻 🔬
+
+**FastAPI** ✔ 👆 📣 🌖 ℹ & 🔬 👆 🔢.
+
+➡️ ✊ 👉 🈸 🖼:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial001_py310.py!}
+ ```
+
+🔢 🔢 `q` 🆎 `Union[str, None]` (⚖️ `str | None` 🐍 3️⃣.1️⃣0️⃣), 👈 ⛓ 👈 ⚫️ 🆎 `str` ✋️ 💪 `None`, & 👐, 🔢 💲 `None`, FastAPI 🔜 💭 ⚫️ 🚫 ✔.
+
+!!! note
+ FastAPI 🔜 💭 👈 💲 `q` 🚫 ✔ ↩️ 🔢 💲 `= None`.
+
+ `Union` `Union[str, None]` 🔜 ✔ 👆 👨🎨 🤝 👆 👍 🐕🦺 & 🔍 ❌.
+
+## 🌖 🔬
+
+👥 🔜 🛠️ 👈 ✋️ `q` 📦, 🕐❔ ⚫️ 🚚, **🚮 📐 🚫 📉 5️⃣0️⃣ 🦹**.
+
+### 🗄 `Query`
+
+🏆 👈, 🥇 🗄 `Query` ⚪️➡️ `fastapi`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002_py310.py!}
+ ```
+
+## ⚙️ `Query` 🔢 💲
+
+& 🔜 ⚙️ ⚫️ 🔢 💲 👆 🔢, ⚒ 🔢 `max_length` 5️⃣0️⃣:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002_py310.py!}
+ ```
+
+👥 ✔️ ❎ 🔢 💲 `None` 🔢 ⏮️ `Query()`, 👥 💪 🔜 ⚒ 🔢 💲 ⏮️ 🔢 `Query(default=None)`, ⚫️ 🍦 🎏 🎯 ⚖ 👈 🔢 💲.
+
+:
+
+```Python
+q: Union[str, None] = Query(default=None)
+```
+
+...⚒ 🔢 📦, 🎏:
+
+```Python
+q: Union[str, None] = None
+```
+
+& 🐍 3️⃣.1️⃣0️⃣ & 🔛:
+
+```Python
+q: str | None = Query(default=None)
+```
+
+...⚒ 🔢 📦, 🎏:
+
+```Python
+q: str | None = None
+```
+
+✋️ ⚫️ 📣 ⚫️ 🎯 💆♂ 🔢 🔢.
+
+!!! info
+ ✔️ 🤯 👈 🌅 ⚠ 🍕 ⚒ 🔢 📦 🍕:
+
+ ```Python
+ = None
+ ```
+
+ ⚖️:
+
+ ```Python
+ = Query(default=None)
+ ```
+
+ ⚫️ 🔜 ⚙️ 👈 `None` 🔢 💲, & 👈 🌌 ⚒ 🔢 **🚫 ✔**.
+
+ `Union[str, None]` 🍕 ✔ 👆 👨🎨 🚚 👻 🐕🦺, ✋️ ⚫️ 🚫 ⚫️❔ 💬 FastAPI 👈 👉 🔢 🚫 ✔.
+
+⤴️, 👥 💪 🚶♀️ 🌅 🔢 `Query`. 👉 💼, `max_length` 🔢 👈 ✔ 🎻:
+
+```Python
+q: Union[str, None] = Query(default=None, max_length=50)
+```
+
+👉 🔜 ✔ 📊, 🎦 🆑 ❌ 🕐❔ 📊 🚫 ☑, & 📄 🔢 🗄 🔗 *➡ 🛠️*.
+
+## 🚮 🌅 🔬
+
+👆 💪 🚮 🔢 `min_length`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial003_py310.py!}
+ ```
+
+## 🚮 🥔 🧬
+
+👆 💪 🔬 🥔 🧬 👈 🔢 🔜 🏏:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial004.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial004_py310.py!}
+ ```
+
+👉 🎯 🥔 🧬 ✅ 👈 📨 🔢 💲:
+
+* `^`: ▶️ ⏮️ 📄 🦹, 🚫 ✔️ 🦹 ⏭.
+* `fixedquery`: ✔️ ☑ 💲 `fixedquery`.
+* `$`: 🔚 📤, 🚫 ✔️ 🙆 🌖 🦹 ⏮️ `fixedquery`.
+
+🚥 👆 💭 💸 ⏮️ 🌐 👉 **"🥔 🧬"** 💭, 🚫 😟. 👫 🏋️ ❔ 📚 👫👫. 👆 💪 📚 💩 🍵 💆♂ 🥔 🧬.
+
+✋️ 🕐❔ 👆 💪 👫 & 🚶 & 💡 👫, 💭 👈 👆 💪 ⏪ ⚙️ 👫 🔗 **FastAPI**.
+
+## 🔢 💲
+
+🎏 🌌 👈 👆 💪 🚶♀️ `None` 💲 `default` 🔢, 👆 💪 🚶♀️ 🎏 💲.
+
+➡️ 💬 👈 👆 💚 📣 `q` 🔢 🔢 ✔️ `min_length` `3`, & ✔️ 🔢 💲 `"fixedquery"`:
+
+```Python hl_lines="7"
+{!../../../docs_src/query_params_str_validations/tutorial005.py!}
+```
+
+!!! note
+ ✔️ 🔢 💲 ⚒ 🔢 📦.
+
+## ⚒ ⚫️ ✔
+
+🕐❔ 👥 🚫 💪 📣 🌅 🔬 ⚖️ 🗃, 👥 💪 ⚒ `q` 🔢 🔢 ✔ 🚫 📣 🔢 💲, 💖:
+
+```Python
+q: str
+```
+
+↩️:
+
+```Python
+q: Union[str, None] = None
+```
+
+✋️ 👥 🔜 📣 ⚫️ ⏮️ `Query`, 🖼 💖:
+
+```Python
+q: Union[str, None] = Query(default=None, min_length=3)
+```
+
+, 🕐❔ 👆 💪 📣 💲 ✔ ⏪ ⚙️ `Query`, 👆 💪 🎯 🚫 📣 🔢 💲:
+
+```Python hl_lines="7"
+{!../../../docs_src/query_params_str_validations/tutorial006.py!}
+```
+
+### ✔ ⏮️ ❕ (`...`)
+
+📤 🎛 🌌 🎯 📣 👈 💲 ✔. 👆 💪 ⚒ `default` 🔢 🔑 💲 `...`:
+
+```Python hl_lines="7"
+{!../../../docs_src/query_params_str_validations/tutorial006b.py!}
+```
+
+!!! info
+ 🚥 👆 🚫 👀 👈 `...` ⏭: ⚫️ 🎁 👁 💲, ⚫️ 🍕 🐍 & 🤙 "❕".
+
+ ⚫️ ⚙️ Pydantic & FastAPI 🎯 📣 👈 💲 ✔.
+
+👉 🔜 ➡️ **FastAPI** 💭 👈 👉 🔢 ✔.
+
+### ✔ ⏮️ `None`
+
+👆 💪 📣 👈 🔢 💪 🚫 `None`, ✋️ 👈 ⚫️ ✔. 👉 🔜 ⚡ 👩💻 📨 💲, 🚥 💲 `None`.
+
+👈, 👆 💪 📣 👈 `None` ☑ 🆎 ✋️ ⚙️ `default=...`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006c.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006c_py310.py!}
+ ```
+
+!!! tip
+ Pydantic, ❔ ⚫️❔ 🏋️ 🌐 💽 🔬 & 🛠️ FastAPI, ✔️ 🎁 🎭 🕐❔ 👆 ⚙️ `Optional` ⚖️ `Union[Something, None]` 🍵 🔢 💲, 👆 💪 ✍ 🌅 🔃 ⚫️ Pydantic 🩺 🔃 ✔ 📦 🏑.
+
+### ⚙️ Pydantic `Required` ↩️ ❕ (`...`)
+
+🚥 👆 💭 😬 ⚙️ `...`, 👆 💪 🗄 & ⚙️ `Required` ⚪️➡️ Pydantic:
+
+```Python hl_lines="2 8"
+{!../../../docs_src/query_params_str_validations/tutorial006d.py!}
+```
+
+!!! tip
+ 💭 👈 🌅 💼, 🕐❔ 🕳 🚚, 👆 💪 🎯 🚫 `default` 🔢, 👆 🛎 🚫 ✔️ ⚙️ `...` 🚫 `Required`.
+
+## 🔢 🔢 📇 / 💗 💲
+
+🕐❔ 👆 🔬 🔢 🔢 🎯 ⏮️ `Query` 👆 💪 📣 ⚫️ 📨 📇 💲, ⚖️ 🙆♀ 🎏 🌌, 📨 💗 💲.
+
+🖼, 📣 🔢 🔢 `q` 👈 💪 😑 💗 🕰 📛, 👆 💪 ✍:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011_py310.py!}
+ ```
+
+⤴️, ⏮️ 📛 💖:
+
+```
+http://localhost:8000/items/?q=foo&q=bar
+```
+
+👆 🔜 📨 💗 `q` *🔢 🔢'* 💲 (`foo` & `bar`) 🐍 `list` 🔘 👆 *➡ 🛠️ 🔢*, *🔢 🔢* `q`.
+
+, 📨 👈 📛 🔜:
+
+```JSON
+{
+ "q": [
+ "foo",
+ "bar"
+ ]
+}
+```
+
+!!! tip
+ 📣 🔢 🔢 ⏮️ 🆎 `list`, 💖 🖼 🔛, 👆 💪 🎯 ⚙️ `Query`, ⏪ ⚫️ 🔜 🔬 📨 💪.
+
+🎓 🛠️ 🩺 🔜 ℹ ➡️, ✔ 💗 💲:
+
+
+
+### 🔢 🔢 📇 / 💗 💲 ⏮️ 🔢
+
+& 👆 💪 🔬 🔢 `list` 💲 🚥 👌 🚚:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial012.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial012_py39.py!}
+ ```
+
+🚥 👆 🚶:
+
+```
+http://localhost:8000/items/
+```
+
+🔢 `q` 🔜: `["foo", "bar"]` & 👆 📨 🔜:
+
+```JSON
+{
+ "q": [
+ "foo",
+ "bar"
+ ]
+}
+```
+
+#### ⚙️ `list`
+
+👆 💪 ⚙️ `list` 🔗 ↩️ `List[str]` (⚖️ `list[str]` 🐍 3️⃣.9️⃣ ➕):
+
+```Python hl_lines="7"
+{!../../../docs_src/query_params_str_validations/tutorial013.py!}
+```
+
+!!! note
+ ✔️ 🤯 👈 👉 💼, FastAPI 🏆 🚫 ✅ 🎚 📇.
+
+ 🖼, `List[int]` 🔜 ✅ (& 📄) 👈 🎚 📇 🔢. ✋️ `list` 😞 🚫🔜.
+
+## 📣 🌅 🗃
+
+👆 💪 🚮 🌅 ℹ 🔃 🔢.
+
+👈 ℹ 🔜 🔌 🏗 🗄 & ⚙️ 🧾 👩💻 🔢 & 🔢 🧰.
+
+!!! note
+ ✔️ 🤯 👈 🎏 🧰 5️⃣📆 ✔️ 🎏 🎚 🗄 🐕🦺.
+
+ 👫 💪 🚫 🎦 🌐 ➕ ℹ 📣, 👐 🌅 💼, ❌ ⚒ ⏪ 📄 🛠️.
+
+👆 💪 🚮 `title`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial007.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial007_py310.py!}
+ ```
+
+& `description`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/query_params_str_validations/tutorial008.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/query_params_str_validations/tutorial008_py310.py!}
+ ```
+
+## 📛 🔢
+
+🌈 👈 👆 💚 🔢 `item-query`.
+
+💖:
+
+```
+http://127.0.0.1:8000/items/?item-query=foobaritems
+```
+
+✋️ `item-query` 🚫 ☑ 🐍 🔢 📛.
+
+🔐 🔜 `item_query`.
+
+✋️ 👆 💪 ⚫️ ⚫️❔ `item-query`...
+
+⤴️ 👆 💪 📣 `alias`, & 👈 📛 ⚫️❔ 🔜 ⚙️ 🔎 🔢 💲:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial009.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial009_py310.py!}
+ ```
+
+## 😛 🔢
+
+🔜 ➡️ 💬 👆 🚫 💖 👉 🔢 🚫🔜.
+
+👆 ✔️ 👈 ⚫️ 📤 ⏪ ↩️ 📤 👩💻 ⚙️ ⚫️, ✋️ 👆 💚 🩺 🎯 🎦 ⚫️ 😢.
+
+⤴️ 🚶♀️ 🔢 `deprecated=True` `Query`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/query_params_str_validations/tutorial010.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/query_params_str_validations/tutorial010_py310.py!}
+ ```
+
+🩺 🔜 🎦 ⚫️ 💖 👉:
+
+
+
+## 🚫 ⚪️➡️ 🗄
+
+🚫 🔢 🔢 ⚪️➡️ 🏗 🗄 🔗 (& ➡️, ⚪️➡️ 🏧 🧾 ⚙️), ⚒ 🔢 `include_in_schema` `Query` `False`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial014.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial014_py310.py!}
+ ```
+
+## 🌃
+
+👆 💪 📣 🌖 🔬 & 🗃 👆 🔢.
+
+💊 🔬 & 🗃:
+
+* `alias`
+* `title`
+* `description`
+* `deprecated`
+
+🔬 🎯 🎻:
+
+* `min_length`
+* `max_length`
+* `regex`
+
+👫 🖼 👆 👀 ❔ 📣 🔬 `str` 💲.
+
+👀 ⏭ 📃 👀 ❔ 📣 🔬 🎏 🆎, 💖 🔢.
diff --git a/docs/em/docs/tutorial/query-params.md b/docs/em/docs/tutorial/query-params.md
new file mode 100644
index 000000000..ccb235c15
--- /dev/null
+++ b/docs/em/docs/tutorial/query-params.md
@@ -0,0 +1,225 @@
+# 🔢 🔢
+
+🕐❔ 👆 📣 🎏 🔢 🔢 👈 🚫 🍕 ➡ 🔢, 👫 🔁 🔬 "🔢" 🔢.
+
+```Python hl_lines="9"
+{!../../../docs_src/query_params/tutorial001.py!}
+```
+
+🔢 ⚒ 🔑-💲 👫 👈 🚶 ⏮️ `?` 📛, 🎏 `&` 🦹.
+
+🖼, 📛:
+
+```
+http://127.0.0.1:8000/items/?skip=0&limit=10
+```
+
+...🔢 🔢:
+
+* `skip`: ⏮️ 💲 `0`
+* `limit`: ⏮️ 💲 `10`
+
+👫 🍕 📛, 👫 "🛎" 🎻.
+
+✋️ 🕐❔ 👆 📣 👫 ⏮️ 🐍 🆎 (🖼 🔛, `int`), 👫 🗜 👈 🆎 & ✔ 🛡 ⚫️.
+
+🌐 🎏 🛠️ 👈 ⚖ ➡ 🔢 ✔ 🔢 🔢:
+
+* 👨🎨 🐕🦺 (🎲)
+* 💽 "✍"
+* 💽 🔬
+* 🏧 🧾
+
+## 🔢
+
+🔢 🔢 🚫 🔧 🍕 ➡, 👫 💪 📦 & 💪 ✔️ 🔢 💲.
+
+🖼 🔛 👫 ✔️ 🔢 💲 `skip=0` & `limit=10`.
+
+, 🔜 📛:
+
+```
+http://127.0.0.1:8000/items/
+```
+
+🔜 🎏 🔜:
+
+```
+http://127.0.0.1:8000/items/?skip=0&limit=10
+```
+
+✋️ 🚥 👆 🚶, 🖼:
+
+```
+http://127.0.0.1:8000/items/?skip=20
+```
+
+🔢 💲 👆 🔢 🔜:
+
+* `skip=20`: ↩️ 👆 ⚒ ⚫️ 📛
+* `limit=10`: ↩️ 👈 🔢 💲
+
+## 📦 🔢
+
+🎏 🌌, 👆 💪 📣 📦 🔢 🔢, ⚒ 👫 🔢 `None`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params/tutorial002_py310.py!}
+ ```
+
+👉 💼, 🔢 🔢 `q` 🔜 📦, & 🔜 `None` 🔢.
+
+!!! check
+ 👀 👈 **FastAPI** 🙃 🥃 👀 👈 ➡ 🔢 `item_id` ➡ 🔢 & `q` 🚫,, ⚫️ 🔢 🔢.
+
+## 🔢 🔢 🆎 🛠️
+
+👆 💪 📣 `bool` 🆎, & 👫 🔜 🗜:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params/tutorial003_py310.py!}
+ ```
+
+👉 💼, 🚥 👆 🚶:
+
+```
+http://127.0.0.1:8000/items/foo?short=1
+```
+
+⚖️
+
+```
+http://127.0.0.1:8000/items/foo?short=True
+```
+
+⚖️
+
+```
+http://127.0.0.1:8000/items/foo?short=true
+```
+
+⚖️
+
+```
+http://127.0.0.1:8000/items/foo?short=on
+```
+
+⚖️
+
+```
+http://127.0.0.1:8000/items/foo?short=yes
+```
+
+⚖️ 🙆 🎏 💼 📈 (🔠, 🥇 🔤 🔠, ♒️), 👆 🔢 🔜 👀 🔢 `short` ⏮️ `bool` 💲 `True`. ⏪ `False`.
+
+
+## 💗 ➡ & 🔢 🔢
+
+👆 💪 📣 💗 ➡ 🔢 & 🔢 🔢 🎏 🕰, **FastAPI** 💭 ❔ ❔.
+
+& 👆 🚫 ✔️ 📣 👫 🙆 🎯 ✔.
+
+👫 🔜 🔬 📛:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="8 10"
+ {!> ../../../docs_src/query_params/tutorial004.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="6 8"
+ {!> ../../../docs_src/query_params/tutorial004_py310.py!}
+ ```
+
+## ✔ 🔢 🔢
+
+🕐❔ 👆 📣 🔢 💲 🚫-➡ 🔢 (🔜, 👥 ✔️ 🕴 👀 🔢 🔢), ⤴️ ⚫️ 🚫 ✔.
+
+🚥 👆 🚫 💚 🚮 🎯 💲 ✋️ ⚒ ⚫️ 📦, ⚒ 🔢 `None`.
+
+✋️ 🕐❔ 👆 💚 ⚒ 🔢 🔢 ✔, 👆 💪 🚫 📣 🙆 🔢 💲:
+
+```Python hl_lines="6-7"
+{!../../../docs_src/query_params/tutorial005.py!}
+```
+
+📥 🔢 🔢 `needy` ✔ 🔢 🔢 🆎 `str`.
+
+🚥 👆 📂 👆 🖥 📛 💖:
+
+```
+http://127.0.0.1:8000/items/foo-item
+```
+
+...🍵 ❎ ✔ 🔢 `needy`, 👆 🔜 👀 ❌ 💖:
+
+```JSON
+{
+ "detail": [
+ {
+ "loc": [
+ "query",
+ "needy"
+ ],
+ "msg": "field required",
+ "type": "value_error.missing"
+ }
+ ]
+}
+```
+
+`needy` 🚚 🔢, 👆 🔜 💪 ⚒ ⚫️ 📛:
+
+```
+http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
+```
+
+...👉 🔜 👷:
+
+```JSON
+{
+ "item_id": "foo-item",
+ "needy": "sooooneedy"
+}
+```
+
+& ↗️, 👆 💪 🔬 🔢 ✔, ✔️ 🔢 💲, & 🍕 📦:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params/tutorial006.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params/tutorial006_py310.py!}
+ ```
+
+👉 💼, 📤 3️⃣ 🔢 🔢:
+
+* `needy`, ✔ `str`.
+* `skip`, `int` ⏮️ 🔢 💲 `0`.
+* `limit`, 📦 `int`.
+
+!!! tip
+ 👆 💪 ⚙️ `Enum`Ⓜ 🎏 🌌 ⏮️ [➡ 🔢](path-params.md#predefined-values){.internal-link target=_blank}.
diff --git a/docs/em/docs/tutorial/request-files.md b/docs/em/docs/tutorial/request-files.md
new file mode 100644
index 000000000..26631823f
--- /dev/null
+++ b/docs/em/docs/tutorial/request-files.md
@@ -0,0 +1,186 @@
+# 📨 📁
+
+👆 💪 🔬 📁 📂 👩💻 ⚙️ `File`.
+
+!!! info
+ 📨 📂 📁, 🥇 ❎ `python-multipart`.
+
+ 🤶 Ⓜ. `pip install python-multipart`.
+
+ 👉 ↩️ 📂 📁 📨 "📨 💽".
+
+## 🗄 `File`
+
+🗄 `File` & `UploadFile` ⚪️➡️ `fastapi`:
+
+```Python hl_lines="1"
+{!../../../docs_src/request_files/tutorial001.py!}
+```
+
+## 🔬 `File` 🔢
+
+✍ 📁 🔢 🎏 🌌 👆 🔜 `Body` ⚖️ `Form`:
+
+```Python hl_lines="7"
+{!../../../docs_src/request_files/tutorial001.py!}
+```
+
+!!! info
+ `File` 🎓 👈 😖 🔗 ⚪️➡️ `Form`.
+
+ ✋️ 💭 👈 🕐❔ 👆 🗄 `Query`, `Path`, `File` & 🎏 ⚪️➡️ `fastapi`, 👈 🤙 🔢 👈 📨 🎁 🎓.
+
+!!! tip
+ 📣 📁 💪, 👆 💪 ⚙️ `File`, ↩️ ⏪ 🔢 🔜 🔬 🔢 🔢 ⚖️ 💪 (🎻) 🔢.
+
+📁 🔜 📂 "📨 💽".
+
+🚥 👆 📣 🆎 👆 *➡ 🛠️ 🔢* 🔢 `bytes`, **FastAPI** 🔜 ✍ 📁 👆 & 👆 🔜 📨 🎚 `bytes`.
+
+✔️ 🤯 👈 👉 ⛓ 👈 🎂 🎚 🔜 🏪 💾. 👉 🔜 👷 👍 🤪 📁.
+
+✋️ 📤 📚 💼 ❔ 👆 💪 💰 ⚪️➡️ ⚙️ `UploadFile`.
+
+## 📁 🔢 ⏮️ `UploadFile`
+
+🔬 📁 🔢 ⏮️ 🆎 `UploadFile`:
+
+```Python hl_lines="12"
+{!../../../docs_src/request_files/tutorial001.py!}
+```
+
+⚙️ `UploadFile` ✔️ 📚 📈 🤭 `bytes`:
+
+* 👆 🚫 ✔️ ⚙️ `File()` 🔢 💲 🔢.
+* ⚫️ ⚙️ "🧵" 📁:
+ * 📁 🏪 💾 🆙 🔆 📐 📉, & ⏮️ 🚶♀️ 👉 📉 ⚫️ 🔜 🏪 💾.
+* 👉 ⛓ 👈 ⚫️ 🔜 👷 👍 ⭕ 📁 💖 🖼, 📹, ⭕ 💱, ♒️. 🍵 😩 🌐 💾.
+* 👆 💪 🤚 🗃 ⚪️➡️ 📂 📁.
+* ⚫️ ✔️ 📁-💖 `async` 🔢.
+* ⚫️ 🎦 ☑ 🐍 `SpooledTemporaryFile` 🎚 👈 👆 💪 🚶♀️ 🔗 🎏 🗃 👈 ⌛ 📁-💖 🎚.
+
+### `UploadFile`
+
+`UploadFile` ✔️ 📄 🔢:
+
+* `filename`: `str` ⏮️ ⏮️ 📁 📛 👈 📂 (✅ `myimage.jpg`).
+* `content_type`: `str` ⏮️ 🎚 🆎 (📁 🆎 / 📻 🆎) (✅ `image/jpeg`).
+* `file`: `SpooledTemporaryFile` ( 📁-💖 🎚). 👉 ☑ 🐍 📁 👈 👆 💪 🚶♀️ 🔗 🎏 🔢 ⚖️ 🗃 👈 ⌛ "📁-💖" 🎚.
+
+`UploadFile` ✔️ 📄 `async` 👩🔬. 👫 🌐 🤙 🔗 📁 👩🔬 🔘 (⚙️ 🔗 `SpooledTemporaryFile`).
+
+* `write(data)`: ✍ `data` (`str` ⚖️ `bytes`) 📁.
+* `read(size)`: ✍ `size` (`int`) 🔢/🦹 📁.
+* `seek(offset)`: 🚶 🔢 🧘 `offset` (`int`) 📁.
+ * 🤶 Ⓜ., `await myfile.seek(0)` 🔜 🚶 ▶️ 📁.
+ * 👉 ✴️ ⚠ 🚥 👆 🏃 `await myfile.read()` 🕐 & ⤴️ 💪 ✍ 🎚 🔄.
+* `close()`: 🔐 📁.
+
+🌐 👫 👩🔬 `async` 👩🔬, 👆 💪 "⌛" 👫.
+
+🖼, 🔘 `async` *➡ 🛠️ 🔢* 👆 💪 🤚 🎚 ⏮️:
+
+```Python
+contents = await myfile.read()
+```
+
+🚥 👆 🔘 😐 `def` *➡ 🛠️ 🔢*, 👆 💪 🔐 `UploadFile.file` 🔗, 🖼:
+
+```Python
+contents = myfile.file.read()
+```
+
+!!! note "`async` 📡 ℹ"
+ 🕐❔ 👆 ⚙️ `async` 👩🔬, **FastAPI** 🏃 📁 👩🔬 🧵 & ⌛ 👫.
+
+!!! note "💃 📡 ℹ"
+ **FastAPI**'Ⓜ `UploadFile` 😖 🔗 ⚪️➡️ **💃**'Ⓜ `UploadFile`, ✋️ 🚮 💪 🍕 ⚒ ⚫️ 🔗 ⏮️ **Pydantic** & 🎏 🍕 FastAPI.
+
+## ⚫️❔ "📨 💽"
+
+🌌 🕸 📨 (``) 📨 💽 💽 🛎 ⚙️ "🎁" 🔢 👈 📊, ⚫️ 🎏 ⚪️➡️ 🎻.
+
+**FastAPI** 🔜 ⚒ 💭 ✍ 👈 📊 ⚪️➡️ ▶️️ 🥉 ↩️ 🎻.
+
+!!! note "📡 ℹ"
+ 📊 ⚪️➡️ 📨 🛎 🗜 ⚙️ "📻 🆎" `application/x-www-form-urlencoded` 🕐❔ ⚫️ 🚫 🔌 📁.
+
+ ✋️ 🕐❔ 📨 🔌 📁, ⚫️ 🗜 `multipart/form-data`. 🚥 👆 ⚙️ `File`, **FastAPI** 🔜 💭 ⚫️ ✔️ 🤚 📁 ⚪️➡️ ☑ 🍕 💪.
+
+ 🚥 👆 💚 ✍ 🌖 🔃 👉 🔢 & 📨 🏑, 👳 🏇 🕸 🩺 POST.
+
+!!! warning
+ 👆 💪 📣 💗 `File` & `Form` 🔢 *➡ 🛠️*, ✋️ 👆 💪 🚫 📣 `Body` 🏑 👈 👆 ⌛ 📨 🎻, 📨 🔜 ✔️ 💪 🗜 ⚙️ `multipart/form-data` ↩️ `application/json`.
+
+ 👉 🚫 🚫 **FastAPI**, ⚫️ 🍕 🇺🇸🔍 🛠️.
+
+## 📦 📁 📂
+
+👆 💪 ⚒ 📁 📦 ⚙️ 🐩 🆎 ✍ & ⚒ 🔢 💲 `None`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9 17"
+ {!> ../../../docs_src/request_files/tutorial001_02.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7 14"
+ {!> ../../../docs_src/request_files/tutorial001_02_py310.py!}
+ ```
+
+## `UploadFile` ⏮️ 🌖 🗃
+
+👆 💪 ⚙️ `File()` ⏮️ `UploadFile`, 🖼, ⚒ 🌖 🗃:
+
+```Python hl_lines="13"
+{!../../../docs_src/request_files/tutorial001_03.py!}
+```
+
+## 💗 📁 📂
+
+⚫️ 💪 📂 📚 📁 🎏 🕰.
+
+👫 🔜 👨💼 🎏 "📨 🏑" 📨 ⚙️ "📨 💽".
+
+⚙️ 👈, 📣 📇 `bytes` ⚖️ `UploadFile`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="10 15"
+ {!> ../../../docs_src/request_files/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="8 13"
+ {!> ../../../docs_src/request_files/tutorial002_py39.py!}
+ ```
+
+👆 🔜 📨, 📣, `list` `bytes` ⚖️ `UploadFile`Ⓜ.
+
+!!! note "📡 ℹ"
+ 👆 💪 ⚙️ `from starlette.responses import HTMLResponse`.
+
+ **FastAPI** 🚚 🎏 `starlette.responses` `fastapi.responses` 🏪 👆, 👩💻. ✋️ 🌅 💪 📨 👟 🔗 ⚪️➡️ 💃.
+
+### 💗 📁 📂 ⏮️ 🌖 🗃
+
+& 🎏 🌌 ⏭, 👆 💪 ⚙️ `File()` ⚒ 🌖 🔢, `UploadFile`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/request_files/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="16"
+ {!> ../../../docs_src/request_files/tutorial003_py39.py!}
+ ```
+
+## 🌃
+
+⚙️ `File`, `bytes`, & `UploadFile` 📣 📁 📂 📨, 📨 📨 💽.
diff --git a/docs/em/docs/tutorial/request-forms-and-files.md b/docs/em/docs/tutorial/request-forms-and-files.md
new file mode 100644
index 000000000..99aeca000
--- /dev/null
+++ b/docs/em/docs/tutorial/request-forms-and-files.md
@@ -0,0 +1,35 @@
+# 📨 📨 & 📁
+
+👆 💪 🔬 📁 & 📨 🏑 🎏 🕰 ⚙️ `File` & `Form`.
+
+!!! info
+ 📨 📂 📁 & /⚖️ 📨 📊, 🥇 ❎ `python-multipart`.
+
+ 🤶 Ⓜ. `pip install python-multipart`.
+
+## 🗄 `File` & `Form`
+
+```Python hl_lines="1"
+{!../../../docs_src/request_forms_and_files/tutorial001.py!}
+```
+
+## 🔬 `File` & `Form` 🔢
+
+✍ 📁 & 📨 🔢 🎏 🌌 👆 🔜 `Body` ⚖️ `Query`:
+
+```Python hl_lines="8"
+{!../../../docs_src/request_forms_and_files/tutorial001.py!}
+```
+
+📁 & 📨 🏑 🔜 📂 📨 📊 & 👆 🔜 📨 📁 & 📨 🏑.
+
+& 👆 💪 📣 📁 `bytes` & `UploadFile`.
+
+!!! warning
+ 👆 💪 📣 💗 `File` & `Form` 🔢 *➡ 🛠️*, ✋️ 👆 💪 🚫 📣 `Body` 🏑 👈 👆 ⌛ 📨 🎻, 📨 🔜 ✔️ 💪 🗜 ⚙️ `multipart/form-data` ↩️ `application/json`.
+
+ 👉 🚫 🚫 **FastAPI**, ⚫️ 🍕 🇺🇸🔍 🛠️.
+
+## 🌃
+
+⚙️ `File` & `Form` 👯♂️ 🕐❔ 👆 💪 📨 💽 & 📁 🎏 📨.
diff --git a/docs/em/docs/tutorial/request-forms.md b/docs/em/docs/tutorial/request-forms.md
new file mode 100644
index 000000000..fa74adae5
--- /dev/null
+++ b/docs/em/docs/tutorial/request-forms.md
@@ -0,0 +1,58 @@
+# 📨 💽
+
+🕐❔ 👆 💪 📨 📨 🏑 ↩️ 🎻, 👆 💪 ⚙️ `Form`.
+
+!!! info
+ ⚙️ 📨, 🥇 ❎ `python-multipart`.
+
+ 🤶 Ⓜ. `pip install python-multipart`.
+
+## 🗄 `Form`
+
+🗄 `Form` ⚪️➡️ `fastapi`:
+
+```Python hl_lines="1"
+{!../../../docs_src/request_forms/tutorial001.py!}
+```
+
+## 🔬 `Form` 🔢
+
+✍ 📨 🔢 🎏 🌌 👆 🔜 `Body` ⚖️ `Query`:
+
+```Python hl_lines="7"
+{!../../../docs_src/request_forms/tutorial001.py!}
+```
+
+🖼, 1️⃣ 🌌 Oauth2️⃣ 🔧 💪 ⚙️ (🤙 "🔐 💧") ⚫️ ✔ 📨 `username` & `password` 📨 🏑.
+
+🔌 🚚 🏑 ⚫️❔ 📛 `username` & `password`, & 📨 📨 🏑, 🚫 🎻.
+
+⏮️ `Form` 👆 💪 📣 🎏 📳 ⏮️ `Body` (& `Query`, `Path`, `Cookie`), 🔌 🔬, 🖼, 📛 (✅ `user-name` ↩️ `username`), ♒️.
+
+!!! info
+ `Form` 🎓 👈 😖 🔗 ⚪️➡️ `Body`.
+
+!!! tip
+ 📣 📨 💪, 👆 💪 ⚙️ `Form` 🎯, ↩️ 🍵 ⚫️ 🔢 🔜 🔬 🔢 🔢 ⚖️ 💪 (🎻) 🔢.
+
+## 🔃 "📨 🏑"
+
+🌌 🕸 📨 (``) 📨 💽 💽 🛎 ⚙️ "🎁" 🔢 👈 📊, ⚫️ 🎏 ⚪️➡️ 🎻.
+
+**FastAPI** 🔜 ⚒ 💭 ✍ 👈 📊 ⚪️➡️ ▶️️ 🥉 ↩️ 🎻.
+
+!!! note "📡 ℹ"
+ 📊 ⚪️➡️ 📨 🛎 🗜 ⚙️ "📻 🆎" `application/x-www-form-urlencoded`.
+
+ ✋️ 🕐❔ 📨 🔌 📁, ⚫️ 🗜 `multipart/form-data`. 👆 🔜 ✍ 🔃 🚚 📁 ⏭ 📃.
+
+ 🚥 👆 💚 ✍ 🌖 🔃 👉 🔢 & 📨 🏑, 👳 🏇 🕸 🩺 POST.
+
+!!! warning
+ 👆 💪 📣 💗 `Form` 🔢 *➡ 🛠️*, ✋️ 👆 💪 🚫 📣 `Body` 🏑 👈 👆 ⌛ 📨 🎻, 📨 🔜 ✔️ 💪 🗜 ⚙️ `application/x-www-form-urlencoded` ↩️ `application/json`.
+
+ 👉 🚫 🚫 **FastAPI**, ⚫️ 🍕 🇺🇸🔍 🛠️.
+
+## 🌃
+
+⚙️ `Form` 📣 📨 💽 🔢 🔢.
diff --git a/docs/em/docs/tutorial/response-model.md b/docs/em/docs/tutorial/response-model.md
new file mode 100644
index 000000000..6ea4413f8
--- /dev/null
+++ b/docs/em/docs/tutorial/response-model.md
@@ -0,0 +1,481 @@
+# 📨 🏷 - 📨 🆎
+
+👆 💪 📣 🆎 ⚙️ 📨 ✍ *➡ 🛠️ 🔢* **📨 🆎**.
+
+👆 💪 ⚙️ **🆎 ✍** 🎏 🌌 👆 🔜 🔢 💽 🔢 **🔢**, 👆 💪 ⚙️ Pydantic 🏷, 📇, 📖, 📊 💲 💖 🔢, 🎻, ♒️.
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="18 23"
+ {!> ../../../docs_src/response_model/tutorial001_01.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="18 23"
+ {!> ../../../docs_src/response_model/tutorial001_01_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="16 21"
+ {!> ../../../docs_src/response_model/tutorial001_01_py310.py!}
+ ```
+
+FastAPI 🔜 ⚙️ 👉 📨 🆎:
+
+* **✔** 📨 💽.
+ * 🚥 💽 ❌ (✅ 👆 ❌ 🏑), ⚫️ ⛓ 👈 *👆* 📱 📟 💔, 🚫 🛬 ⚫️❔ ⚫️ 🔜, & ⚫️ 🔜 📨 💽 ❌ ↩️ 🛬 ❌ 💽. 👉 🌌 👆 & 👆 👩💻 💪 🎯 👈 👫 🔜 📨 💽 & 💽 💠 📈.
+* 🚮 **🎻 🔗** 📨, 🗄 *➡ 🛠️*.
+ * 👉 🔜 ⚙️ **🏧 🩺**.
+ * ⚫️ 🔜 ⚙️ 🏧 👩💻 📟 ⚡ 🧰.
+
+✋️ 🏆 🥈:
+
+* ⚫️ 🔜 **📉 & ⛽** 🔢 📊 ⚫️❔ 🔬 📨 🆎.
+ * 👉 ✴️ ⚠ **💂♂**, 👥 🔜 👀 🌅 👈 🔛.
+
+## `response_model` 🔢
+
+📤 💼 🌐❔ 👆 💪 ⚖️ 💚 📨 💽 👈 🚫 ⚫️❔ ⚫️❔ 🆎 📣.
+
+🖼, 👆 💪 💚 **📨 📖** ⚖️ 💽 🎚, ✋️ **📣 ⚫️ Pydantic 🏷**. 👉 🌌 Pydantic 🏷 🔜 🌐 💽 🧾, 🔬, ♒️. 🎚 👈 👆 📨 (✅ 📖 ⚖️ 💽 🎚).
+
+🚥 👆 🚮 📨 🆎 ✍, 🧰 & 👨🎨 🔜 😭 ⏮️ (☑) ❌ 💬 👆 👈 👆 🔢 🛬 🆎 (✅#️⃣) 👈 🎏 ⚪️➡️ ⚫️❔ 👆 📣 (✅ Pydantic 🏷).
+
+📚 💼, 👆 💪 ⚙️ *➡ 🛠️ 👨🎨* 🔢 `response_model` ↩️ 📨 🆎.
+
+👆 💪 ⚙️ `response_model` 🔢 🙆 *➡ 🛠️*:
+
+* `@app.get()`
+* `@app.post()`
+* `@app.put()`
+* `@app.delete()`
+* ♒️.
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="17 22 24-27"
+ {!> ../../../docs_src/response_model/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="17 22 24-27"
+ {!> ../../../docs_src/response_model/tutorial001_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="17 22 24-27"
+ {!> ../../../docs_src/response_model/tutorial001_py310.py!}
+ ```
+
+!!! note
+ 👀 👈 `response_model` 🔢 "👨🎨" 👩🔬 (`get`, `post`, ♒️). 🚫 👆 *➡ 🛠️ 🔢*, 💖 🌐 🔢 & 💪.
+
+`response_model` 📨 🎏 🆎 👆 🔜 📣 Pydantic 🏷 🏑,, ⚫️ 💪 Pydantic 🏷, ✋️ ⚫️ 💪, ✅ `list` Pydantic 🏷, 💖 `List[Item]`.
+
+FastAPI 🔜 ⚙️ 👉 `response_model` 🌐 💽 🧾, 🔬, ♒️. & **🗜 & ⛽ 🔢 📊** 🚮 🆎 📄.
+
+!!! tip
+ 🚥 👆 ✔️ ⚠ 🆎 ✅ 👆 👨🎨, ✍, ♒️, 👆 💪 📣 🔢 📨 🆎 `Any`.
+
+ 👈 🌌 👆 💬 👨🎨 👈 👆 😫 🛬 🕳. ✋️ FastAPI 🔜 💽 🧾, 🔬, 🖥, ♒️. ⏮️ `response_model`.
+
+### `response_model` 📫
+
+🚥 👆 📣 👯♂️ 📨 🆎 & `response_model`, `response_model` 🔜 ✊ 📫 & ⚙️ FastAPI.
+
+👉 🌌 👆 💪 🚮 ☑ 🆎 ✍ 👆 🔢 🕐❔ 👆 🛬 🆎 🎏 🌘 📨 🏷, ⚙️ 👨🎨 & 🧰 💖 ✍. & 👆 💪 ✔️ FastAPI 💽 🔬, 🧾, ♒️. ⚙️ `response_model`.
+
+👆 💪 ⚙️ `response_model=None` ❎ 🏗 📨 🏷 👈 *➡ 🛠️*, 👆 5️⃣📆 💪 ⚫️ 🚥 👆 ❎ 🆎 ✍ 👜 👈 🚫 ☑ Pydantic 🏑, 👆 🔜 👀 🖼 👈 1️⃣ 📄 🔛.
+
+## 📨 🎏 🔢 💽
+
+📥 👥 📣 `UserIn` 🏷, ⚫️ 🔜 🔌 🔢 🔐:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9 11"
+ {!> ../../../docs_src/response_model/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7 9"
+ {!> ../../../docs_src/response_model/tutorial002_py310.py!}
+ ```
+
+!!! info
+ ⚙️ `EmailStr`, 🥇 ❎ `email_validator`.
+
+ 🤶 Ⓜ. `pip install email-validator`
+ ⚖️ `pip install pydantic[email]`.
+
+& 👥 ⚙️ 👉 🏷 📣 👆 🔢 & 🎏 🏷 📣 👆 🔢:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/response_model/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="16"
+ {!> ../../../docs_src/response_model/tutorial002_py310.py!}
+ ```
+
+🔜, 🕐❔ 🖥 🏗 👩💻 ⏮️ 🔐, 🛠️ 🔜 📨 🎏 🔐 📨.
+
+👉 💼, ⚫️ 💪 🚫 ⚠, ↩️ ⚫️ 🎏 👩💻 📨 🔐.
+
+✋️ 🚥 👥 ⚙️ 🎏 🏷 ➕1️⃣ *➡ 🛠️*, 👥 💪 📨 👆 👩💻 🔐 🔠 👩💻.
+
+!!! danger
+ 🙅 🏪 ✅ 🔐 👩💻 ⚖️ 📨 ⚫️ 📨 💖 👉, 🚥 👆 💭 🌐 ⚠ & 👆 💭 ⚫️❔ 👆 🔨.
+
+## 🚮 🔢 🏷
+
+👥 💪 ↩️ ✍ 🔢 🏷 ⏮️ 🔢 🔐 & 🔢 🏷 🍵 ⚫️:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9 11 16"
+ {!> ../../../docs_src/response_model/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="9 11 16"
+ {!> ../../../docs_src/response_model/tutorial003_py310.py!}
+ ```
+
+📥, ✋️ 👆 *➡ 🛠️ 🔢* 🛬 🎏 🔢 👩💻 👈 🔌 🔐:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/response_model/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/response_model/tutorial003_py310.py!}
+ ```
+
+...👥 📣 `response_model` 👆 🏷 `UserOut`, 👈 🚫 🔌 🔐:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/response_model/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/response_model/tutorial003_py310.py!}
+ ```
+
+, **FastAPI** 🔜 ✊ 💅 🖥 👅 🌐 💽 👈 🚫 📣 🔢 🏷 (⚙️ Pydantic).
+
+### `response_model` ⚖️ 📨 🆎
+
+👉 💼, ↩️ 2️⃣ 🏷 🎏, 🚥 👥 ✍ 🔢 📨 🆎 `UserOut`, 👨🎨 & 🧰 🔜 😭 👈 👥 🛬 ❌ 🆎, 📚 🎏 🎓.
+
+👈 ⚫️❔ 👉 🖼 👥 ✔️ 📣 ⚫️ `response_model` 🔢.
+
+...✋️ 😣 👂 🔛 👀 ❔ ❎ 👈.
+
+## 📨 🆎 & 💽 🖥
+
+➡️ 😣 ⚪️➡️ ⏮️ 🖼. 👥 💚 **✍ 🔢 ⏮️ 1️⃣ 🆎** ✋️ 📨 🕳 👈 🔌 **🌅 💽**.
+
+👥 💚 FastAPI 🚧 **🖥** 📊 ⚙️ 📨 🏷.
+
+⏮️ 🖼, ↩️ 🎓 🎏, 👥 ✔️ ⚙️ `response_model` 🔢. ✋️ 👈 ⛓ 👈 👥 🚫 🤚 🐕🦺 ⚪️➡️ 👨🎨 & 🧰 ✅ 🔢 📨 🆎.
+
+✋️ 🌅 💼 🌐❔ 👥 💪 🕳 💖 👉, 👥 💚 🏷 **⛽/❎** 📊 👉 🖼.
+
+& 👈 💼, 👥 💪 ⚙️ 🎓 & 🧬 ✊ 📈 🔢 **🆎 ✍** 🤚 👍 🐕🦺 👨🎨 & 🧰, & 🤚 FastAPI **💽 🖥**.
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9-13 15-16 20"
+ {!> ../../../docs_src/response_model/tutorial003_01.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7-10 13-14 18"
+ {!> ../../../docs_src/response_model/tutorial003_01_py310.py!}
+ ```
+
+⏮️ 👉, 👥 🤚 🏭 🐕🦺, ⚪️➡️ 👨🎨 & ✍ 👉 📟 ☑ ⚖ 🆎, ✋️ 👥 🤚 💽 🖥 ⚪️➡️ FastAPI.
+
+❔ 🔨 👉 👷 ❓ ➡️ ✅ 👈 👅. 👶
+
+### 🆎 ✍ & 🏭
+
+🥇 ➡️ 👀 ❔ 👨🎨, ✍ & 🎏 🧰 🔜 👀 👉.
+
+`BaseUser` ✔️ 🧢 🏑. ⤴️ `UserIn` 😖 ⚪️➡️ `BaseUser` & 🚮 `password` 🏑,, ⚫️ 🔜 🔌 🌐 🏑 ⚪️➡️ 👯♂️ 🏷.
+
+👥 ✍ 🔢 📨 🆎 `BaseUser`, ✋️ 👥 🤙 🛬 `UserIn` 👐.
+
+👨🎨, ✍, & 🎏 🧰 🏆 🚫 😭 🔃 👉 ↩️, ⌨ ⚖, `UserIn` 🏿 `BaseUser`, ❔ ⛓ ⚫️ *☑* 🆎 🕐❔ ⚫️❔ ⌛ 🕳 👈 `BaseUser`.
+
+### FastAPI 💽 🖥
+
+🔜, FastAPI, ⚫️ 🔜 👀 📨 🆎 & ⚒ 💭 👈 ⚫️❔ 👆 📨 🔌 **🕴** 🏑 👈 📣 🆎.
+
+FastAPI 🔨 📚 👜 🔘 ⏮️ Pydantic ⚒ 💭 👈 📚 🎏 🚫 🎓 🧬 🚫 ⚙️ 📨 💽 🖥, ⏪ 👆 💪 🔚 🆙 🛬 🌅 🌅 💽 🌘 ⚫️❔ 👆 📈.
+
+👉 🌌, 👆 💪 🤚 🏆 👯♂️ 🌏: 🆎 ✍ ⏮️ **🏭 🐕🦺** & **💽 🖥**.
+
+## 👀 ⚫️ 🩺
+
+🕐❔ 👆 👀 🏧 🩺, 👆 💪 ✅ 👈 🔢 🏷 & 🔢 🏷 🔜 👯♂️ ✔️ 👫 👍 🎻 🔗:
+
+
+
+& 👯♂️ 🏷 🔜 ⚙️ 🎓 🛠️ 🧾:
+
+
+
+## 🎏 📨 🆎 ✍
+
+📤 5️⃣📆 💼 🌐❔ 👆 📨 🕳 👈 🚫 ☑ Pydantic 🏑 & 👆 ✍ ⚫️ 🔢, 🕴 🤚 🐕🦺 🚚 🏭 (👨🎨, ✍, ♒️).
+
+### 📨 📨 🔗
+
+🏆 ⚠ 💼 🔜 [🛬 📨 🔗 🔬 ⏪ 🏧 🩺](../advanced/response-directly.md){.internal-link target=_blank}.
+
+```Python hl_lines="8 10-11"
+{!> ../../../docs_src/response_model/tutorial003_02.py!}
+```
+
+👉 🙅 💼 🍵 🔁 FastAPI ↩️ 📨 🆎 ✍ 🎓 (⚖️ 🏿) `Response`.
+
+& 🧰 🔜 😄 ↩️ 👯♂️ `RedirectResponse` & `JSONResponse` 🏿 `Response`, 🆎 ✍ ☑.
+
+### ✍ 📨 🏿
+
+👆 💪 ⚙️ 🏿 `Response` 🆎 ✍:
+
+```Python hl_lines="8-9"
+{!> ../../../docs_src/response_model/tutorial003_03.py!}
+```
+
+👉 🔜 👷 ↩️ `RedirectResponse` 🏿 `Response`, & FastAPI 🔜 🔁 🍵 👉 🙅 💼.
+
+### ❌ 📨 🆎 ✍
+
+✋️ 🕐❔ 👆 📨 🎏 ❌ 🎚 👈 🚫 ☑ Pydantic 🆎 (✅ 💽 🎚) & 👆 ✍ ⚫️ 💖 👈 🔢, FastAPI 🔜 🔄 ✍ Pydantic 📨 🏷 ⚪️➡️ 👈 🆎 ✍, & 🔜 ❌.
+
+🎏 🔜 🔨 🚥 👆 ✔️ 🕳 💖 🇪🇺 🖖 🎏 🆎 🌐❔ 1️⃣ ⚖️ 🌅 👫 🚫 ☑ Pydantic 🆎, 🖼 👉 🔜 ❌ 👶:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/response_model/tutorial003_04.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/response_model/tutorial003_04_py310.py!}
+ ```
+
+...👉 ❌ ↩️ 🆎 ✍ 🚫 Pydantic 🆎 & 🚫 👁 `Response` 🎓 ⚖️ 🏿, ⚫️ 🇪🇺 (🙆 2️⃣) 🖖 `Response` & `dict`.
+
+### ❎ 📨 🏷
+
+▶️ ⚪️➡️ 🖼 🔛, 👆 5️⃣📆 🚫 💚 ✔️ 🔢 💽 🔬, 🧾, 🖥, ♒️. 👈 🎭 FastAPI.
+
+✋️ 👆 💪 💚 🚧 📨 🆎 ✍ 🔢 🤚 🐕🦺 ⚪️➡️ 🧰 💖 👨🎨 & 🆎 ☑ (✅ ✍).
+
+👉 💼, 👆 💪 ❎ 📨 🏷 ⚡ ⚒ `response_model=None`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/response_model/tutorial003_05.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/response_model/tutorial003_05_py310.py!}
+ ```
+
+👉 🔜 ⚒ FastAPI 🚶 📨 🏷 ⚡ & 👈 🌌 👆 💪 ✔️ 🙆 📨 🆎 ✍ 👆 💪 🍵 ⚫️ 🤕 👆 FastAPI 🈸. 👶
+
+## 📨 🏷 🔢 🔢
+
+👆 📨 🏷 💪 ✔️ 🔢 💲, 💖:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="11 13-14"
+ {!> ../../../docs_src/response_model/tutorial004.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="11 13-14"
+ {!> ../../../docs_src/response_model/tutorial004_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="9 11-12"
+ {!> ../../../docs_src/response_model/tutorial004_py310.py!}
+ ```
+
+* `description: Union[str, None] = None` (⚖️ `str | None = None` 🐍 3️⃣.1️⃣0️⃣) ✔️ 🔢 `None`.
+* `tax: float = 10.5` ✔️ 🔢 `10.5`.
+* `tags: List[str] = []` 🔢 🛁 📇: `[]`.
+
+✋️ 👆 💪 💚 🚫 👫 ⚪️➡️ 🏁 🚥 👫 🚫 🤙 🏪.
+
+🖼, 🚥 👆 ✔️ 🏷 ⏮️ 📚 📦 🔢 ☁ 💽, ✋️ 👆 🚫 💚 📨 📶 📏 🎻 📨 🌕 🔢 💲.
+
+### ⚙️ `response_model_exclude_unset` 🔢
+
+👆 💪 ⚒ *➡ 🛠️ 👨🎨* 🔢 `response_model_exclude_unset=True`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/response_model/tutorial004.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/response_model/tutorial004_py39.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/response_model/tutorial004_py310.py!}
+ ```
+
+& 👈 🔢 💲 🏆 🚫 🔌 📨, 🕴 💲 🤙 ⚒.
+
+, 🚥 👆 📨 📨 👈 *➡ 🛠️* 🏬 ⏮️ 🆔 `foo`, 📨 (🚫 ✅ 🔢 💲) 🔜:
+
+```JSON
+{
+ "name": "Foo",
+ "price": 50.2
+}
+```
+
+!!! info
+ FastAPI ⚙️ Pydantic 🏷 `.dict()` ⏮️ 🚮 `exclude_unset` 🔢 🏆 👉.
+
+!!! info
+ 👆 💪 ⚙️:
+
+ * `response_model_exclude_defaults=True`
+ * `response_model_exclude_none=True`
+
+ 🔬 Pydantic 🩺 `exclude_defaults` & `exclude_none`.
+
+#### 📊 ⏮️ 💲 🏑 ⏮️ 🔢
+
+✋️ 🚥 👆 📊 ✔️ 💲 🏷 🏑 ⏮️ 🔢 💲, 💖 🏬 ⏮️ 🆔 `bar`:
+
+```Python hl_lines="3 5"
+{
+ "name": "Bar",
+ "description": "The bartenders",
+ "price": 62,
+ "tax": 20.2
+}
+```
+
+👫 🔜 🔌 📨.
+
+#### 📊 ⏮️ 🎏 💲 🔢
+
+🚥 📊 ✔️ 🎏 💲 🔢 🕐, 💖 🏬 ⏮️ 🆔 `baz`:
+
+```Python hl_lines="3 5-6"
+{
+ "name": "Baz",
+ "description": None,
+ "price": 50.2,
+ "tax": 10.5,
+ "tags": []
+}
+```
+
+FastAPI 🙃 🥃 (🤙, Pydantic 🙃 🥃) 🤔 👈, ✋️ `description`, `tax`, & `tags` ✔️ 🎏 💲 🔢, 👫 ⚒ 🎯 (↩️ ✊ ⚪️➡️ 🔢).
+
+, 👫 🔜 🔌 🎻 📨.
+
+!!! tip
+ 👀 👈 🔢 💲 💪 🕳, 🚫 🕴 `None`.
+
+ 👫 💪 📇 (`[]`), `float` `10.5`, ♒️.
+
+### `response_model_include` & `response_model_exclude`
+
+👆 💪 ⚙️ *➡ 🛠️ 👨🎨* 🔢 `response_model_include` & `response_model_exclude`.
+
+👫 ✊ `set` `str` ⏮️ 📛 🔢 🔌 (❎ 🎂) ⚖️ 🚫 (✅ 🎂).
+
+👉 💪 ⚙️ ⏩ ⌨ 🚥 👆 ✔️ 🕴 1️⃣ Pydantic 🏷 & 💚 ❎ 💽 ⚪️➡️ 🔢.
+
+!!! tip
+ ✋️ ⚫️ 👍 ⚙️ 💭 🔛, ⚙️ 💗 🎓, ↩️ 👫 🔢.
+
+ 👉 ↩️ 🎻 🔗 🏗 👆 📱 🗄 (& 🩺) 🔜 1️⃣ 🏁 🏷, 🚥 👆 ⚙️ `response_model_include` ⚖️ `response_model_exclude` 🚫 🔢.
+
+ 👉 ✔ `response_model_by_alias` 👈 👷 ➡.
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="31 37"
+ {!> ../../../docs_src/response_model/tutorial005.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="29 35"
+ {!> ../../../docs_src/response_model/tutorial005_py310.py!}
+ ```
+
+!!! tip
+ ❕ `{"name", "description"}` ✍ `set` ⏮️ 📚 2️⃣ 💲.
+
+ ⚫️ 🌓 `set(["name", "description"])`.
+
+#### ⚙️ `list`Ⓜ ↩️ `set`Ⓜ
+
+🚥 👆 💭 ⚙️ `set` & ⚙️ `list` ⚖️ `tuple` ↩️, FastAPI 🔜 🗜 ⚫️ `set` & ⚫️ 🔜 👷 ☑:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="31 37"
+ {!> ../../../docs_src/response_model/tutorial006.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="29 35"
+ {!> ../../../docs_src/response_model/tutorial006_py310.py!}
+ ```
+
+## 🌃
+
+⚙️ *➡ 🛠️ 👨🎨* 🔢 `response_model` 🔬 📨 🏷 & ✴️ 🚚 📢 💽 ⛽ 👅.
+
+⚙️ `response_model_exclude_unset` 📨 🕴 💲 🎯 ⚒.
diff --git a/docs/em/docs/tutorial/response-status-code.md b/docs/em/docs/tutorial/response-status-code.md
new file mode 100644
index 000000000..e5149de7d
--- /dev/null
+++ b/docs/em/docs/tutorial/response-status-code.md
@@ -0,0 +1,89 @@
+# 📨 👔 📟
+
+🎏 🌌 👆 💪 ✔ 📨 🏷, 👆 💪 📣 🇺🇸🔍 👔 📟 ⚙️ 📨 ⏮️ 🔢 `status_code` 🙆 *➡ 🛠️*:
+
+* `@app.get()`
+* `@app.post()`
+* `@app.put()`
+* `@app.delete()`
+* ♒️.
+
+```Python hl_lines="6"
+{!../../../docs_src/response_status_code/tutorial001.py!}
+```
+
+!!! note
+ 👀 👈 `status_code` 🔢 "👨🎨" 👩🔬 (`get`, `post`, ♒️). 🚫 👆 *➡ 🛠️ 🔢*, 💖 🌐 🔢 & 💪.
+
+`status_code` 🔢 📨 🔢 ⏮️ 🇺🇸🔍 👔 📟.
+
+!!! info
+ `status_code` 💪 👐 📨 `IntEnum`, ✅ 🐍 `http.HTTPStatus`.
+
+⚫️ 🔜:
+
+* 📨 👈 👔 📟 📨.
+* 📄 ⚫️ ✅ 🗄 🔗 ( & , 👩💻 🔢):
+
+
+
+!!! note
+ 📨 📟 (👀 ⏭ 📄) 🎦 👈 📨 🔨 🚫 ✔️ 💪.
+
+ FastAPI 💭 👉, & 🔜 🏭 🗄 🩺 👈 🇵🇸 📤 🙅♂ 📨 💪.
+
+## 🔃 🇺🇸🔍 👔 📟
+
+!!! note
+ 🚥 👆 ⏪ 💭 ⚫️❔ 🇺🇸🔍 👔 📟, 🚶 ⏭ 📄.
+
+🇺🇸🔍, 👆 📨 🔢 👔 📟 3️⃣ 9️⃣ 🍕 📨.
+
+👫 👔 📟 ✔️ 📛 🔗 🤔 👫, ✋️ ⚠ 🍕 🔢.
+
+📏:
+
+* `100` & 🔛 "ℹ". 👆 🛎 ⚙️ 👫 🔗. 📨 ⏮️ 👫 👔 📟 🚫🔜 ✔️ 💪.
+* **`200`** & 🔛 "🏆" 📨. 👫 🕐 👆 🔜 ⚙️ 🏆.
+ * `200` 🔢 👔 📟, ❔ ⛓ 🌐 "👌".
+ * ➕1️⃣ 🖼 🔜 `201`, "✍". ⚫️ 🛎 ⚙️ ⏮️ 🏗 🆕 ⏺ 💽.
+ * 🎁 💼 `204`, "🙅♂ 🎚". 👉 📨 ⚙️ 🕐❔ 📤 🙅♂ 🎚 📨 👩💻, & 📨 🔜 🚫 ✔️ 💪.
+* **`300`** & 🔛 "❎". 📨 ⏮️ 👫 👔 📟 5️⃣📆 ⚖️ 5️⃣📆 🚫 ✔️ 💪, 🌖 `304`, "🚫 🔀", ❔ 🔜 🚫 ✔️ 1️⃣.
+* **`400`** & 🔛 "👩💻 ❌" 📨. 👫 🥈 🆎 👆 🔜 🎲 ⚙️ 🏆.
+ * 🖼 `404`, "🚫 🔎" 📨.
+ * 💊 ❌ ⚪️➡️ 👩💻, 👆 💪 ⚙️ `400`.
+* `500` & 🔛 💽 ❌. 👆 🌖 🙅 ⚙️ 👫 🔗. 🕐❔ 🕳 🚶 ❌ 🍕 👆 🈸 📟, ⚖️ 💽, ⚫️ 🔜 🔁 📨 1️⃣ 👫 👔 📟.
+
+!!! tip
+ 💭 🌅 🔃 🔠 👔 📟 & ❔ 📟 ⚫️❔, ✅ 🏇 🧾 🔃 🇺🇸🔍 👔 📟.
+
+## ⌨ 💭 📛
+
+➡️ 👀 ⏮️ 🖼 🔄:
+
+```Python hl_lines="6"
+{!../../../docs_src/response_status_code/tutorial001.py!}
+```
+
+`201` 👔 📟 "✍".
+
+✋️ 👆 🚫 ✔️ ✍ ⚫️❔ 🔠 👉 📟 ⛓.
+
+👆 💪 ⚙️ 🏪 🔢 ⚪️➡️ `fastapi.status`.
+
+```Python hl_lines="1 6"
+{!../../../docs_src/response_status_code/tutorial002.py!}
+```
+
+👫 🏪, 👫 🧑🤝🧑 🎏 🔢, ✋️ 👈 🌌 👆 💪 ⚙️ 👨🎨 📋 🔎 👫:
+
+
+
+!!! note "📡 ℹ"
+ 👆 💪 ⚙️ `from starlette import status`.
+
+ **FastAPI** 🚚 🎏 `starlette.status` `fastapi.status` 🏪 👆, 👩💻. ✋️ ⚫️ 👟 🔗 ⚪️➡️ 💃.
+
+## 🔀 🔢
+
+⏪, [🏧 👩💻 🦮](../advanced/response-change-status-code.md){.internal-link target=_blank}, 👆 🔜 👀 ❔ 📨 🎏 👔 📟 🌘 🔢 👆 📣 📥.
diff --git a/docs/em/docs/tutorial/schema-extra-example.md b/docs/em/docs/tutorial/schema-extra-example.md
new file mode 100644
index 000000000..d5bf8810a
--- /dev/null
+++ b/docs/em/docs/tutorial/schema-extra-example.md
@@ -0,0 +1,141 @@
+# 📣 📨 🖼 💽
+
+👆 💪 📣 🖼 💽 👆 📱 💪 📨.
+
+📥 📚 🌌 ⚫️.
+
+## Pydantic `schema_extra`
+
+👆 💪 📣 `example` Pydantic 🏷 ⚙️ `Config` & `schema_extra`, 🔬 Pydantic 🩺: 🔗 🛃:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="15-23"
+ {!> ../../../docs_src/schema_extra_example/tutorial001.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="13-21"
+ {!> ../../../docs_src/schema_extra_example/tutorial001_py310.py!}
+ ```
+
+👈 ➕ ℹ 🔜 🚮-🔢 **🎻 🔗** 👈 🏷, & ⚫️ 🔜 ⚙️ 🛠️ 🩺.
+
+!!! tip
+ 👆 💪 ⚙️ 🎏 ⚒ ↔ 🎻 🔗 & 🚮 👆 👍 🛃 ➕ ℹ.
+
+ 🖼 👆 💪 ⚙️ ⚫️ 🚮 🗃 🕸 👩💻 🔢, ♒️.
+
+## `Field` 🌖 ❌
+
+🕐❔ ⚙️ `Field()` ⏮️ Pydantic 🏷, 👆 💪 📣 ➕ ℹ **🎻 🔗** 🚶♀️ 🙆 🎏 ❌ ❌ 🔢.
+
+👆 💪 ⚙️ 👉 🚮 `example` 🔠 🏑:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="4 10-13"
+ {!> ../../../docs_src/schema_extra_example/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="2 8-11"
+ {!> ../../../docs_src/schema_extra_example/tutorial002_py310.py!}
+ ```
+
+!!! warning
+ 🚧 🤯 👈 📚 ➕ ❌ 🚶♀️ 🏆 🚫 🚮 🙆 🔬, 🕴 ➕ ℹ, 🧾 🎯.
+
+## `example` & `examples` 🗄
+
+🕐❔ ⚙️ 🙆:
+
+* `Path()`
+* `Query()`
+* `Header()`
+* `Cookie()`
+* `Body()`
+* `Form()`
+* `File()`
+
+👆 💪 📣 💽 `example` ⚖️ 👪 `examples` ⏮️ 🌖 ℹ 👈 🔜 🚮 **🗄**.
+
+### `Body` ⏮️ `example`
+
+📥 👥 🚶♀️ `example` 📊 ⌛ `Body()`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="20-25"
+ {!> ../../../docs_src/schema_extra_example/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="18-23"
+ {!> ../../../docs_src/schema_extra_example/tutorial003_py310.py!}
+ ```
+
+### 🖼 🩺 🎚
+
+⏮️ 🙆 👩🔬 🔛 ⚫️ 🔜 👀 💖 👉 `/docs`:
+
+
+
+### `Body` ⏮️ 💗 `examples`
+
+👐 👁 `example`, 👆 💪 🚶♀️ `examples` ⚙️ `dict` ⏮️ **💗 🖼**, 🔠 ⏮️ ➕ ℹ 👈 🔜 🚮 **🗄** 💁♂️.
+
+🔑 `dict` 🔬 🔠 🖼, & 🔠 💲 ➕1️⃣ `dict`.
+
+🔠 🎯 🖼 `dict` `examples` 💪 🔌:
+
+* `summary`: 📏 📛 🖼.
+* `description`: 📏 📛 👈 💪 🔌 ✍ ✍.
+* `value`: 👉 ☑ 🖼 🎦, ✅ `dict`.
+* `externalValue`: 🎛 `value`, 📛 ☝ 🖼. 👐 👉 5️⃣📆 🚫 🐕🦺 📚 🧰 `value`.
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="21-47"
+ {!> ../../../docs_src/schema_extra_example/tutorial004.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="19-45"
+ {!> ../../../docs_src/schema_extra_example/tutorial004_py310.py!}
+ ```
+
+### 🖼 🩺 🎚
+
+⏮️ `examples` 🚮 `Body()` `/docs` 🔜 👀 💖:
+
+
+
+## 📡 ℹ
+
+!!! warning
+ 👉 📶 📡 ℹ 🔃 🐩 **🎻 🔗** & **🗄**.
+
+ 🚥 💭 🔛 ⏪ 👷 👆, 👈 💪 🥃, & 👆 🎲 🚫 💪 👉 ℹ, 💭 🆓 🚶 👫.
+
+🕐❔ 👆 🚮 🖼 🔘 Pydantic 🏷, ⚙️ `schema_extra` ⚖️ `Field(example="something")` 👈 🖼 🚮 **🎻 🔗** 👈 Pydantic 🏷.
+
+& 👈 **🎻 🔗** Pydantic 🏷 🔌 **🗄** 👆 🛠️, & ⤴️ ⚫️ ⚙️ 🩺 🎚.
+
+**🎻 🔗** 🚫 🤙 ✔️ 🏑 `example` 🐩. ⏮️ ⏬ 🎻 🔗 🔬 🏑 `examples`, ✋️ 🗄 3️⃣.0️⃣.3️⃣ ⚓️ 🔛 🗝 ⏬ 🎻 🔗 👈 🚫 ✔️ `examples`.
+
+, 🗄 3️⃣.0️⃣.3️⃣ 🔬 🚮 👍 `example` 🔀 ⏬ **🎻 🔗** ⚫️ ⚙️, 🎏 🎯 (✋️ ⚫️ 👁 `example`, 🚫 `examples`), & 👈 ⚫️❔ ⚙️ 🛠️ 🩺 🎚 (⚙️ 🦁 🎚).
+
+, 👐 `example` 🚫 🍕 🎻 🔗, ⚫️ 🍕 🗄 🛃 ⏬ 🎻 🔗, & 👈 ⚫️❔ 🔜 ⚙️ 🩺 🎚.
+
+✋️ 🕐❔ 👆 ⚙️ `example` ⚖️ `examples` ⏮️ 🙆 🎏 🚙 (`Query()`, `Body()`, ♒️.) 📚 🖼 🚫 🚮 🎻 🔗 👈 🔬 👈 💽 (🚫 🗄 👍 ⏬ 🎻 🔗), 👫 🚮 🔗 *➡ 🛠️* 📄 🗄 (🏞 🍕 🗄 👈 ⚙️ 🎻 🔗).
+
+`Path()`, `Query()`, `Header()`, & `Cookie()`, `example` ⚖️ `examples` 🚮 🗄 🔑, `Parameter Object` (🔧).
+
+& `Body()`, `File()`, & `Form()`, `example` ⚖️ `examples` 📊 🚮 🗄 🔑, `Request Body Object`, 🏑 `content`, 🔛 `Media Type Object` (🔧).
+
+🔛 🎏 ✋, 📤 🆕 ⏬ 🗄: **3️⃣.1️⃣.0️⃣**, ⏳ 🚀. ⚫️ ⚓️ 🔛 ⏪ 🎻 🔗 & 🏆 🛠️ ⚪️➡️ 🗄 🛃 ⏬ 🎻 🔗 ❎, 💱 ⚒ ⚪️➡️ ⏮️ ⏬ 🎻 🔗, 🌐 👫 🤪 🔺 📉. 👐, 🦁 🎚 ⏳ 🚫 🐕🦺 🗄 3️⃣.1️⃣.0️⃣,, 🔜, ⚫️ 👍 😣 ⚙️ 💭 🔛.
diff --git a/docs/em/docs/tutorial/security/first-steps.md b/docs/em/docs/tutorial/security/first-steps.md
new file mode 100644
index 000000000..6dec6f2c3
--- /dev/null
+++ b/docs/em/docs/tutorial/security/first-steps.md
@@ -0,0 +1,182 @@
+# 💂♂ - 🥇 🔁
+
+➡️ 🌈 👈 👆 ✔️ 👆 **👩💻** 🛠️ 🆔.
+
+& 👆 ✔️ **🕸** ➕1️⃣ 🆔 ⚖️ 🎏 ➡ 🎏 🆔 (⚖️ 📱 🈸).
+
+& 👆 💚 ✔️ 🌌 🕸 🔓 ⏮️ 👩💻, ⚙️ **🆔** & **🔐**.
+
+👥 💪 ⚙️ **Oauth2️⃣** 🏗 👈 ⏮️ **FastAPI**.
+
+✋️ ➡️ 🖊 👆 🕰 👂 🌕 📏 🔧 🔎 👈 🐥 🍖 ℹ 👆 💪.
+
+➡️ ⚙️ 🧰 🚚 **FastAPI** 🍵 💂♂.
+
+## ❔ ⚫️ 👀
+
+➡️ 🥇 ⚙️ 📟 & 👀 ❔ ⚫️ 👷, & ⤴️ 👥 🔜 👟 🔙 🤔 ⚫️❔ 😥.
+
+## ✍ `main.py`
+
+📁 🖼 📁 `main.py`:
+
+```Python
+{!../../../docs_src/security/tutorial001.py!}
+```
+
+## 🏃 ⚫️
+
+!!! info
+ 🥇 ❎ `python-multipart`.
+
+ 🤶 Ⓜ. `pip install python-multipart`.
+
+ 👉 ↩️ **Oauth2️⃣** ⚙️ "📨 📊" 📨 `username` & `password`.
+
+🏃 🖼 ⏮️:
+
+
+
+!!! check "✔ 🔼 ❗"
+ 👆 ⏪ ✔️ ✨ 🆕 "✔" 🔼.
+
+ & 👆 *➡ 🛠️* ✔️ 🐥 🔒 🔝-▶️️ ↩ 👈 👆 💪 🖊.
+
+& 🚥 👆 🖊 ⚫️, 👆 ✔️ 🐥 ✔ 📨 🆎 `username` & `password` (& 🎏 📦 🏑):
+
+
+
+!!! note
+ ⚫️ 🚫 🤔 ⚫️❔ 👆 🆎 📨, ⚫️ 🏆 🚫 👷. ✋️ 👥 🔜 🤚 📤.
+
+👉 ↗️ 🚫 🕸 🏁 👩💻, ✋️ ⚫️ 👑 🏧 🧰 📄 🖥 🌐 👆 🛠️.
+
+⚫️ 💪 ⚙️ 🕸 🏉 (👈 💪 👆).
+
+⚫️ 💪 ⚙️ 🥉 🥳 🈸 & ⚙️.
+
+& ⚫️ 💪 ⚙️ 👆, ℹ, ✅ & 💯 🎏 🈸.
+
+## `password` 💧
+
+🔜 ➡️ 🚶 🔙 👄 & 🤔 ⚫️❔ 🌐 👈.
+
+`password` "💧" 1️⃣ 🌌 ("💧") 🔬 Oauth2️⃣, 🍵 💂♂ & 🤝.
+
+Oauth2️⃣ 🔧 👈 👩💻 ⚖️ 🛠️ 💪 🔬 💽 👈 🔓 👩💻.
+
+✋️ 👉 💼, 🎏 **FastAPI** 🈸 🔜 🍵 🛠️ & 🤝.
+
+, ➡️ 📄 ⚫️ ⚪️➡️ 👈 📉 ☝ 🎑:
+
+* 👩💻 🆎 `username` & `password` 🕸, & 🎯 `Enter`.
+* 🕸 (🏃♂ 👩💻 🖥) 📨 👈 `username` & `password` 🎯 📛 👆 🛠️ (📣 ⏮️ `tokenUrl="token"`).
+* 🛠️ ✅ 👈 `username` & `password`, & 📨 ⏮️ "🤝" (👥 🚫 🛠️ 🙆 👉).
+ * "🤝" 🎻 ⏮️ 🎚 👈 👥 💪 ⚙️ ⏪ ✔ 👉 👩💻.
+ * 🛎, 🤝 ⚒ 🕛 ⏮️ 🕰.
+ * , 👩💻 🔜 ✔️ 🕹 🔄 ☝ ⏪.
+ * & 🚥 🤝 📎, ⚠ 🌘. ⚫️ 🚫 💖 🧲 🔑 👈 🔜 👷 ♾ (🏆 💼).
+* 🕸 🏪 👈 🤝 🍕 👱.
+* 👩💻 🖊 🕸 🚶 ➕1️⃣ 📄 🕸 🕸 📱.
+* 🕸 💪 ☕ 🌅 💽 ⚪️➡️ 🛠️.
+ * ✋️ ⚫️ 💪 🤝 👈 🎯 🔗.
+ * , 🔓 ⏮️ 👆 🛠️, ⚫️ 📨 🎚 `Authorization` ⏮️ 💲 `Bearer ` ➕ 🤝.
+ * 🚥 🤝 🔌 `foobar`, 🎚 `Authorization` 🎚 🔜: `Bearer foobar`.
+
+## **FastAPI**'Ⓜ `OAuth2PasswordBearer`
+
+**FastAPI** 🚚 📚 🧰, 🎏 🎚 ⚛, 🛠️ 👫 💂♂ ⚒.
+
+👉 🖼 👥 🔜 ⚙️ **Oauth2️⃣**, ⏮️ **🔐** 💧, ⚙️ **📨** 🤝. 👥 👈 ⚙️ `OAuth2PasswordBearer` 🎓.
+
+!!! info
+ "📨" 🤝 🚫 🕴 🎛.
+
+ ✋️ ⚫️ 🏆 1️⃣ 👆 ⚙️ 💼.
+
+ & ⚫️ 💪 🏆 🏆 ⚙️ 💼, 🚥 👆 Oauth2️⃣ 🕴 & 💭 ⚫️❔ ⚫️❔ 📤 ➕1️⃣ 🎛 👈 ♣ 👻 👆 💪.
+
+ 👈 💼, **FastAPI** 🚚 👆 ⏮️ 🧰 🏗 ⚫️.
+
+🕐❔ 👥 ✍ 👐 `OAuth2PasswordBearer` 🎓 👥 🚶♀️ `tokenUrl` 🔢. 👉 🔢 🔌 📛 👈 👩💻 (🕸 🏃 👩💻 🖥) 🔜 ⚙️ 📨 `username` & `password` ✔ 🤚 🤝.
+
+```Python hl_lines="6"
+{!../../../docs_src/security/tutorial001.py!}
+```
+
+!!! tip
+ 📥 `tokenUrl="token"` 🔗 ⚖ 📛 `token` 👈 👥 🚫 ✍. ⚫️ ⚖ 📛, ⚫️ 🌓 `./token`.
+
+ ↩️ 👥 ⚙️ ⚖ 📛, 🚥 👆 🛠️ 🔎 `https://example.com/`, ⤴️ ⚫️ 🔜 🔗 `https://example.com/token`. ✋️ 🚥 👆 🛠️ 🔎 `https://example.com/api/v1/`, ⤴️ ⚫️ 🔜 🔗 `https://example.com/api/v1/token`.
+
+ ⚙️ ⚖ 📛 ⚠ ⚒ 💭 👆 🈸 🚧 👷 🏧 ⚙️ 💼 💖 [⛅ 🗳](../../advanced/behind-a-proxy.md){.internal-link target=_blank}.
+
+👉 🔢 🚫 ✍ 👈 🔗 / *➡ 🛠️*, ✋️ 📣 👈 📛 `/token` 🔜 1️⃣ 👈 👩💻 🔜 ⚙️ 🤚 🤝. 👈 ℹ ⚙️ 🗄, & ⤴️ 🎓 🛠️ 🧾 ⚙️.
+
+👥 🔜 🔜 ✍ ☑ ➡ 🛠️.
+
+!!! info
+ 🚥 👆 📶 ⚠ "✍" 👆 💪 👎 👗 🔢 📛 `tokenUrl` ↩️ `token_url`.
+
+ 👈 ↩️ ⚫️ ⚙️ 🎏 📛 🗄 🔌. 👈 🚥 👆 💪 🔬 🌅 🔃 🙆 👫 💂♂ ⚖ 👆 💪 📁 & 📋 ⚫️ 🔎 🌖 ℹ 🔃 ⚫️.
+
+`oauth2_scheme` 🔢 👐 `OAuth2PasswordBearer`, ✋️ ⚫️ "🇧🇲".
+
+⚫️ 💪 🤙:
+
+```Python
+oauth2_scheme(some, parameters)
+```
+
+, ⚫️ 💪 ⚙️ ⏮️ `Depends`.
+
+### ⚙️ ⚫️
+
+🔜 👆 💪 🚶♀️ 👈 `oauth2_scheme` 🔗 ⏮️ `Depends`.
+
+```Python hl_lines="10"
+{!../../../docs_src/security/tutorial001.py!}
+```
+
+👉 🔗 🔜 🚚 `str` 👈 🛠️ 🔢 `token` *➡ 🛠️ 🔢*.
+
+**FastAPI** 🔜 💭 👈 ⚫️ 💪 ⚙️ 👉 🔗 🔬 "💂♂ ⚖" 🗄 🔗 (& 🏧 🛠️ 🩺).
+
+!!! info "📡 ℹ"
+ **FastAPI** 🔜 💭 👈 ⚫️ 💪 ⚙️ 🎓 `OAuth2PasswordBearer` (📣 🔗) 🔬 💂♂ ⚖ 🗄 ↩️ ⚫️ 😖 ⚪️➡️ `fastapi.security.oauth2.OAuth2`, ❔ 🔄 😖 ⚪️➡️ `fastapi.security.base.SecurityBase`.
+
+ 🌐 💂♂ 🚙 👈 🛠️ ⏮️ 🗄 (& 🏧 🛠️ 🩺) 😖 ⚪️➡️ `SecurityBase`, 👈 ❔ **FastAPI** 💪 💭 ❔ 🛠️ 👫 🗄.
+
+## ⚫️❔ ⚫️ 🔨
+
+⚫️ 🔜 🚶 & 👀 📨 👈 `Authorization` 🎚, ✅ 🚥 💲 `Bearer ` ➕ 🤝, & 🔜 📨 🤝 `str`.
+
+🚥 ⚫️ 🚫 👀 `Authorization` 🎚, ⚖️ 💲 🚫 ✔️ `Bearer ` 🤝, ⚫️ 🔜 📨 ⏮️ 4️⃣0️⃣1️⃣ 👔 📟 ❌ (`UNAUTHORIZED`) 🔗.
+
+👆 🚫 ✔️ ✅ 🚥 🤝 🔀 📨 ❌. 👆 💪 💭 👈 🚥 👆 🔢 🛠️, ⚫️ 🔜 ✔️ `str` 👈 🤝.
+
+👆 💪 🔄 ⚫️ ⏪ 🎓 🩺:
+
+
+
+👥 🚫 ✔ 🔬 🤝, ✋️ 👈 ▶️ ⏪.
+
+## 🌃
+
+, 3️⃣ ⚖️ 4️⃣ ➕ ⏸, 👆 ⏪ ✔️ 🐒 📨 💂♂.
diff --git a/docs/em/docs/tutorial/security/get-current-user.md b/docs/em/docs/tutorial/security/get-current-user.md
new file mode 100644
index 000000000..455cb4f46
--- /dev/null
+++ b/docs/em/docs/tutorial/security/get-current-user.md
@@ -0,0 +1,151 @@
+# 🤚 ⏮️ 👩💻
+
+⏮️ 📃 💂♂ ⚙️ (❔ 🧢 🔛 🔗 💉 ⚙️) 🤝 *➡ 🛠️ 🔢* `token` `str`:
+
+```Python hl_lines="10"
+{!../../../docs_src/security/tutorial001.py!}
+```
+
+✋️ 👈 🚫 👈 ⚠.
+
+➡️ ⚒ ⚫️ 🤝 👥 ⏮️ 👩💻.
+
+## ✍ 👩💻 🏷
+
+🥇, ➡️ ✍ Pydantic 👩💻 🏷.
+
+🎏 🌌 👥 ⚙️ Pydantic 📣 💪, 👥 💪 ⚙️ ⚫️ 🙆 🙆:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="5 12-16"
+ {!> ../../../docs_src/security/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="3 10-14"
+ {!> ../../../docs_src/security/tutorial002_py310.py!}
+ ```
+
+## ✍ `get_current_user` 🔗
+
+➡️ ✍ 🔗 `get_current_user`.
+
+💭 👈 🔗 💪 ✔️ 🎧-🔗 ❓
+
+`get_current_user` 🔜 ✔️ 🔗 ⏮️ 🎏 `oauth2_scheme` 👥 ✍ ⏭.
+
+🎏 👥 🔨 ⏭ *➡ 🛠️* 🔗, 👆 🆕 🔗 `get_current_user` 🔜 📨 `token` `str` ⚪️➡️ 🎧-🔗 `oauth2_scheme`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="25"
+ {!> ../../../docs_src/security/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="23"
+ {!> ../../../docs_src/security/tutorial002_py310.py!}
+ ```
+
+## 🤚 👩💻
+
+`get_current_user` 🔜 ⚙️ (❌) 🚙 🔢 👥 ✍, 👈 ✊ 🤝 `str` & 📨 👆 Pydantic `User` 🏷:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="19-22 26-27"
+ {!> ../../../docs_src/security/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="17-20 24-25"
+ {!> ../../../docs_src/security/tutorial002_py310.py!}
+ ```
+
+## 💉 ⏮️ 👩💻
+
+🔜 👥 💪 ⚙️ 🎏 `Depends` ⏮️ 👆 `get_current_user` *➡ 🛠️*:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="31"
+ {!> ../../../docs_src/security/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="29"
+ {!> ../../../docs_src/security/tutorial002_py310.py!}
+ ```
+
+👀 👈 👥 📣 🆎 `current_user` Pydantic 🏷 `User`.
+
+👉 🔜 ℹ 🇺🇲 🔘 🔢 ⏮️ 🌐 🛠️ & 🆎 ✅.
+
+!!! tip
+ 👆 5️⃣📆 💭 👈 📨 💪 📣 ⏮️ Pydantic 🏷.
+
+ 📥 **FastAPI** 🏆 🚫 🤚 😨 ↩️ 👆 ⚙️ `Depends`.
+
+!!! check
+ 🌌 👉 🔗 ⚙️ 🏗 ✔ 👥 ✔️ 🎏 🔗 (🎏 "☑") 👈 🌐 📨 `User` 🏷.
+
+ 👥 🚫 🚫 ✔️ 🕴 1️⃣ 🔗 👈 💪 📨 👈 🆎 💽.
+
+## 🎏 🏷
+
+👆 💪 🔜 🤚 ⏮️ 👩💻 🔗 *➡ 🛠️ 🔢* & 🙅 ⏮️ 💂♂ 🛠️ **🔗 💉** 🎚, ⚙️ `Depends`.
+
+& 👆 💪 ⚙️ 🙆 🏷 ⚖️ 💽 💂♂ 📄 (👉 💼, Pydantic 🏷 `User`).
+
+✋️ 👆 🚫 🚫 ⚙️ 🎯 💽 🏷, 🎓 ⚖️ 🆎.
+
+👆 💚 ✔️ `id` & `email` & 🚫 ✔️ 🙆 `username` 👆 🏷 ❓ 💭. 👆 💪 ⚙️ 👉 🎏 🧰.
+
+👆 💚 ✔️ `str`❓ ⚖️ `dict`❓ ⚖️ 💽 🎓 🏷 👐 🔗 ❓ ⚫️ 🌐 👷 🎏 🌌.
+
+👆 🤙 🚫 ✔️ 👩💻 👈 🕹 👆 🈸 ✋️ 🤖, 🤖, ⚖️ 🎏 ⚙️, 👈 ✔️ 🔐 🤝 ❓ 🔄, ⚫️ 🌐 👷 🎏.
+
+⚙️ 🙆 😇 🏷, 🙆 😇 🎓, 🙆 😇 💽 👈 👆 💪 👆 🈸. **FastAPI** ✔️ 👆 📔 ⏮️ 🔗 💉 ⚙️.
+
+## 📟 📐
+
+👉 🖼 5️⃣📆 😑 🔁. ✔️ 🤯 👈 👥 🌀 💂♂, 📊 🏷, 🚙 🔢 & *➡ 🛠️* 🎏 📁.
+
+✋️ 📥 🔑 ☝.
+
+💂♂ & 🔗 💉 💩 ✍ 🕐.
+
+& 👆 💪 ⚒ ⚫️ 🏗 👆 💚. & , ✔️ ⚫️ ✍ 🕴 🕐, 👁 🥉. ⏮️ 🌐 💪.
+
+✋️ 👆 💪 ✔️ 💯 🔗 (*➡ 🛠️*) ⚙️ 🎏 💂♂ ⚙️.
+
+& 🌐 👫 (⚖️ 🙆 ↔ 👫 👈 👆 💚) 💪 ✊ 📈 🏤-⚙️ 👫 🔗 ⚖️ 🙆 🎏 🔗 👆 ✍.
+
+& 🌐 👉 💯 *➡ 🛠️* 💪 🤪 3️⃣ ⏸:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="30-32"
+ {!> ../../../docs_src/security/tutorial002.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="28-30"
+ {!> ../../../docs_src/security/tutorial002_py310.py!}
+ ```
+
+## 🌃
+
+👆 💪 🔜 🤚 ⏮️ 👩💻 🔗 👆 *➡ 🛠️ 🔢*.
+
+👥 ⏪ 😬 📤.
+
+👥 💪 🚮 *➡ 🛠️* 👩💻/👩💻 🤙 📨 `username` & `password`.
+
+👈 👟 ⏭.
diff --git a/docs/em/docs/tutorial/security/index.md b/docs/em/docs/tutorial/security/index.md
new file mode 100644
index 000000000..5b507af3e
--- /dev/null
+++ b/docs/em/docs/tutorial/security/index.md
@@ -0,0 +1,101 @@
+# 💂♂ 🎶
+
+📤 📚 🌌 🍵 💂♂, 🤝 & ✔.
+
+& ⚫️ 🛎 🏗 & "⚠" ❔.
+
+📚 🛠️ & ⚙️ 🍵 💂♂ & 🤝 ✊ 🦏 💸 🎯 & 📟 (📚 💼 ⚫️ 💪 5️⃣0️⃣ 💯 ⚖️ 🌅 🌐 📟 ✍).
+
+**FastAPI** 🚚 📚 🧰 ℹ 👆 🙅 ⏮️ **💂♂** 💪, 📉, 🐩 🌌, 🍵 ✔️ 🔬 & 💡 🌐 💂♂ 🔧.
+
+✋️ 🥇, ➡️ ✅ 🤪 🔧.
+
+## 🏃 ❓
+
+🚥 👆 🚫 💅 🔃 🙆 👉 ⚖ & 👆 💪 🚮 💂♂ ⏮️ 🤝 ⚓️ 🔛 🆔 & 🔐 *▶️️ 🔜*, 🚶 ⏭ 📃.
+
+## Oauth2️⃣
+
+Oauth2️⃣ 🔧 👈 🔬 📚 🌌 🍵 🤝 & ✔.
+
+⚫️ 🔬 🔧 & 📔 📚 🏗 ⚙️ 💼.
+
+⚫️ 🔌 🌌 🔓 ⚙️ "🥉 🥳".
+
+👈 ⚫️❔ 🌐 ⚙️ ⏮️ "💳 ⏮️ 👱📔, 🇺🇸🔍, 👱📔, 📂" ⚙️ 🔘.
+
+### ✳ 1️⃣
+
+📤 ✳ 1️⃣, ❔ 📶 🎏 ⚪️➡️ Oauth2️⃣, & 🌖 🏗, ⚫️ 🔌 🔗 🔧 🔛 ❔ 🗜 📻.
+
+⚫️ 🚫 📶 🌟 ⚖️ ⚙️ 🛎.
+
+Oauth2️⃣ 🚫 ✔ ❔ 🗜 📻, ⚫️ ⌛ 👆 ✔️ 👆 🈸 🍦 ⏮️ 🇺🇸🔍.
+
+!!! tip
+ 📄 🔃 **🛠️** 👆 🔜 👀 ❔ ⚒ 🆙 🇺🇸🔍 🆓, ⚙️ Traefik & ➡️ 🗜.
+
+
+## 👩💻 🔗
+
+👩💻 🔗 ➕1️⃣ 🔧, 🧢 🔛 **Oauth2️⃣**.
+
+⚫️ ↔ Oauth2️⃣ ✔ 👜 👈 📶 🌌 Oauth2️⃣, 🔄 ⚒ ⚫️ 🌅 🛠️.
+
+🖼, 🇺🇸🔍 💳 ⚙️ 👩💻 🔗 (❔ 🔘 ⚙️ Oauth2️⃣).
+
+✋️ 👱📔 💳 🚫 🐕🦺 👩💻 🔗. ⚫️ ✔️ 🚮 👍 🍛 Oauth2️⃣.
+
+### 👩💻 (🚫 "👩💻 🔗")
+
+📤 "👩💻" 🔧. 👈 🔄 ❎ 🎏 👜 **👩💻 🔗**, ✋️ 🚫 ⚓️ 🔛 Oauth2️⃣.
+
+, ⚫️ 🏁 🌖 ⚙️.
+
+⚫️ 🚫 📶 🌟 ⚖️ ⚙️ 🛎.
+
+## 🗄
+
+🗄 (⏪ 💭 🦁) 📂 🔧 🏗 🔗 (🔜 🍕 💾 🏛).
+
+**FastAPI** ⚓️ 🔛 **🗄**.
+
+👈 ⚫️❔ ⚒ ⚫️ 💪 ✔️ 💗 🏧 🎓 🧾 🔢, 📟 ⚡, ♒️.
+
+🗄 ✔️ 🌌 🔬 💗 💂♂ "⚖".
+
+⚙️ 👫, 👆 💪 ✊ 📈 🌐 👫 🐩-⚓️ 🧰, 🔌 👉 🎓 🧾 ⚙️.
+
+🗄 🔬 📄 💂♂ ⚖:
+
+* `apiKey`: 🈸 🎯 🔑 👈 💪 👟 ⚪️➡️:
+ * 🔢 🔢.
+ * 🎚.
+ * 🍪.
+* `http`: 🐩 🇺🇸🔍 🤝 ⚙️, 🔌:
+ * `bearer`: 🎚 `Authorization` ⏮️ 💲 `Bearer ` ➕ 🤝. 👉 😖 ⚪️➡️ Oauth2️⃣.
+ * 🇺🇸🔍 🔰 🤝.
+ * 🇺🇸🔍 📰, ♒️.
+* `oauth2`: 🌐 Oauth2️⃣ 🌌 🍵 💂♂ (🤙 "💧").
+ * 📚 👫 💧 ☑ 🏗 ✳ 2️⃣.0️⃣ 🤝 🐕🦺 (💖 🇺🇸🔍, 👱📔, 👱📔, 📂, ♒️):
+ * `implicit`
+ * `clientCredentials`
+ * `authorizationCode`
+ * ✋️ 📤 1️⃣ 🎯 "💧" 👈 💪 👌 ⚙️ 🚚 🤝 🎏 🈸 🔗:
+ * `password`: ⏭ 📃 🔜 📔 🖼 👉.
+* `openIdConnect`: ✔️ 🌌 🔬 ❔ 🔎 Oauth2️⃣ 🤝 📊 🔁.
+ * 👉 🏧 🔍 ⚫️❔ 🔬 👩💻 🔗 🔧.
+
+
+!!! tip
+ 🛠️ 🎏 🤝/✔ 🐕🦺 💖 🇺🇸🔍, 👱📔, 👱📔, 📂, ♒️. 💪 & 📶 ⏩.
+
+ 🌅 🏗 ⚠ 🏗 🤝/✔ 🐕🦺 💖 👈, ✋️ **FastAPI** 🤝 👆 🧰 ⚫️ 💪, ⏪ 🔨 🏋️ 🏋♂ 👆.
+
+## **FastAPI** 🚙
+
+FastAPI 🚚 📚 🧰 🔠 👉 💂♂ ⚖ `fastapi.security` 🕹 👈 📉 ⚙️ 👉 💂♂ 🛠️.
+
+⏭ 📃 👆 🔜 👀 ❔ 🚮 💂♂ 👆 🛠️ ⚙️ 📚 🧰 🚚 **FastAPI**.
+
+& 👆 🔜 👀 ❔ ⚫️ 🤚 🔁 🛠️ 🔘 🎓 🧾 ⚙️.
diff --git a/docs/em/docs/tutorial/security/oauth2-jwt.md b/docs/em/docs/tutorial/security/oauth2-jwt.md
new file mode 100644
index 000000000..bc207c566
--- /dev/null
+++ b/docs/em/docs/tutorial/security/oauth2-jwt.md
@@ -0,0 +1,297 @@
+# Oauth2️⃣ ⏮️ 🔐 (& 🔁), 📨 ⏮️ 🥙 🤝
+
+🔜 👈 👥 ✔️ 🌐 💂♂ 💧, ➡️ ⚒ 🈸 🤙 🔐, ⚙️ 🥙 🤝 & 🔐 🔐 🔁.
+
+👉 📟 🕳 👆 💪 🤙 ⚙️ 👆 🈸, 🖊 🔐 #️⃣ 👆 💽, ♒️.
+
+👥 🔜 ▶️ ⚪️➡️ 🌐❔ 👥 ◀️ ⏮️ 📃 & 📈 ⚫️.
+
+## 🔃 🥙
+
+🥙 ⛓ "🎻 🕸 🤝".
+
+⚫️ 🐩 🚫 🎻 🎚 📏 💧 🎻 🍵 🚀. ⚫️ 👀 💖 👉:
+
+```
+eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
+```
+
+⚫️ 🚫 🗜,, 🙆 💪 🛡 ℹ ⚪️➡️ 🎚.
+
+✋️ ⚫️ 🛑. , 🕐❔ 👆 📨 🤝 👈 👆 ♨, 👆 💪 ✔ 👈 👆 🤙 ♨ ⚫️.
+
+👈 🌌, 👆 💪 ✍ 🤝 ⏮️ 👔, ➡️ 💬, 1️⃣ 🗓️. & ⤴️ 🕐❔ 👩💻 👟 🔙 ⏭ 📆 ⏮️ 🤝, 👆 💭 👈 👩💻 🕹 👆 ⚙️.
+
+⏮️ 🗓️, 🤝 🔜 🕛 & 👩💻 🔜 🚫 ✔ & 🔜 ✔️ 🛑 🔄 🤚 🆕 🤝. & 🚥 👩💻 (⚖️ 🥉 🥳) 🔄 🔀 🤝 🔀 👔, 👆 🔜 💪 🔎 ⚫️, ↩️ 💳 🔜 🚫 🏏.
+
+🚥 👆 💚 🤾 ⏮️ 🥙 🤝 & 👀 ❔ 👫 👷, ✅ https://jwt.io.
+
+## ❎ `python-jose`
+
+👥 💪 ❎ `python-jose` 🏗 & ✔ 🥙 🤝 🐍:
+
+
+
+✔ 🈸 🎏 🌌 ⏭.
+
+⚙️ 🎓:
+
+🆔: `johndoe`
+🔐: `secret`
+
+!!! check
+ 👀 👈 🕳 📟 🔢 🔐 "`secret`", 👥 🕴 ✔️ #️⃣ ⏬.
+
+
+
+🤙 🔗 `/users/me/`, 👆 🔜 🤚 📨:
+
+```JSON
+{
+ "username": "johndoe",
+ "email": "johndoe@example.com",
+ "full_name": "John Doe",
+ "disabled": false
+}
+```
+
+
+
+🚥 👆 📂 👩💻 🧰, 👆 💪 👀 ❔ 📊 📨 🕴 🔌 🤝, 🔐 🕴 📨 🥇 📨 🔓 👩💻 & 🤚 👈 🔐 🤝, ✋️ 🚫 ⏮️:
+
+
+
+!!! note
+ 👀 🎚 `Authorization`, ⏮️ 💲 👈 ▶️ ⏮️ `Bearer `.
+
+## 🏧 ⚙️ ⏮️ `scopes`
+
+Oauth2️⃣ ✔️ 🔑 "↔".
+
+👆 💪 ⚙️ 👫 🚮 🎯 ⚒ ✔ 🥙 🤝.
+
+⤴️ 👆 💪 🤝 👉 🤝 👩💻 🔗 ⚖️ 🥉 🥳, 🔗 ⏮️ 👆 🛠️ ⏮️ ⚒ 🚫.
+
+👆 💪 💡 ❔ ⚙️ 👫 & ❔ 👫 🛠️ 🔘 **FastAPI** ⏪ **🏧 👩💻 🦮**.
+
+## 🌃
+
+⏮️ ⚫️❔ 👆 ✔️ 👀 🆙 🔜, 👆 💪 ⚒ 🆙 🔐 **FastAPI** 🈸 ⚙️ 🐩 💖 Oauth2️⃣ & 🥙.
+
+🌖 🙆 🛠️ 🚚 💂♂ ▶️️ 👍 🏗 📄 🔜.
+
+📚 📦 👈 📉 ⚫️ 📚 ✔️ ⚒ 📚 ⚠ ⏮️ 💽 🏷, 💽, & 💪 ⚒. & 👉 📦 👈 📉 👜 💁♂️ 🌅 🤙 ✔️ 💂♂ ⚠ 🔘.
+
+---
+
+**FastAPI** 🚫 ⚒ 🙆 ⚠ ⏮️ 🙆 💽, 💽 🏷 ⚖️ 🧰.
+
+⚫️ 🤝 👆 🌐 💪 ⚒ 🕐 👈 👖 👆 🏗 🏆.
+
+& 👆 💪 ⚙️ 🔗 📚 👍 🚧 & 🛎 ⚙️ 📦 💖 `passlib` & `python-jose`, ↩️ **FastAPI** 🚫 🚚 🙆 🏗 🛠️ 🛠️ 🔢 📦.
+
+✋️ ⚫️ 🚚 👆 🧰 📉 🛠️ 🌅 💪 🍵 🎯 💪, ⚖, ⚖️ 💂♂.
+
+& 👆 💪 ⚙️ & 🛠️ 🔐, 🐩 🛠️, 💖 Oauth2️⃣ 📶 🙅 🌌.
+
+👆 💪 💡 🌅 **🏧 👩💻 🦮** 🔃 ❔ ⚙️ Oauth2️⃣ "↔", 🌖 👌-🧽 ✔ ⚙️, 📄 👫 🎏 🐩. Oauth2️⃣ ⏮️ ↔ 🛠️ ⚙️ 📚 🦏 🤝 🐕🦺, 💖 👱📔, 🇺🇸🔍, 📂, 🤸♂, 👱📔, ♒️. ✔ 🥉 🥳 🈸 🔗 ⏮️ 👫 🔗 🔛 👨💼 👫 👩💻.
diff --git a/docs/em/docs/tutorial/security/simple-oauth2.md b/docs/em/docs/tutorial/security/simple-oauth2.md
new file mode 100644
index 000000000..765d94039
--- /dev/null
+++ b/docs/em/docs/tutorial/security/simple-oauth2.md
@@ -0,0 +1,315 @@
+# 🙅 Oauth2️⃣ ⏮️ 🔐 & 📨
+
+🔜 ➡️ 🏗 ⚪️➡️ ⏮️ 📃 & 🚮 ❌ 🍕 ✔️ 🏁 💂♂ 💧.
+
+## 🤚 `username` & `password`
+
+👥 🔜 ⚙️ **FastAPI** 💂♂ 🚙 🤚 `username` & `password`.
+
+Oauth2️⃣ ✔ 👈 🕐❔ ⚙️ "🔐 💧" (👈 👥 ⚙️) 👩💻/👩💻 🔜 📨 `username` & `password` 🏑 📨 💽.
+
+& 🔌 💬 👈 🏑 ✔️ 🌟 💖 👈. `user-name` ⚖️ `email` 🚫🔜 👷.
+
+✋️ 🚫 😟, 👆 💪 🎦 ⚫️ 👆 🎋 👆 🏁 👩💻 🕸.
+
+& 👆 💽 🏷 💪 ⚙️ 🙆 🎏 📛 👆 💚.
+
+✋️ 💳 *➡ 🛠️*, 👥 💪 ⚙️ 👉 📛 🔗 ⏮️ 🔌 (& 💪, 🖼, ⚙️ 🛠️ 🛠️ 🧾 ⚙️).
+
+🔌 🇵🇸 👈 `username` & `password` 🔜 📨 📨 💽 (, 🙅♂ 🎻 📥).
+
+### `scope`
+
+🔌 💬 👈 👩💻 💪 📨 ➕1️⃣ 📨 🏑 "`scope`".
+
+📨 🏑 📛 `scope` (⭐), ✋️ ⚫️ 🤙 📏 🎻 ⏮️ "↔" 🎏 🚀.
+
+🔠 "↔" 🎻 (🍵 🚀).
+
+👫 🛎 ⚙️ 📣 🎯 💂♂ ✔, 🖼:
+
+* `users:read` ⚖️ `users:write` ⚠ 🖼.
+* `instagram_basic` ⚙️ 👱📔 / 👱📔.
+* `https://www.googleapis.com/auth/drive` ⚙️ 🇺🇸🔍.
+
+!!! info
+ Oauth2️⃣ "↔" 🎻 👈 📣 🎯 ✔ ✔.
+
+ ⚫️ 🚫 🤔 🚥 ⚫️ ✔️ 🎏 🦹 💖 `:` ⚖️ 🚥 ⚫️ 📛.
+
+ 👈 ℹ 🛠️ 🎯.
+
+ Oauth2️⃣ 👫 🎻.
+
+## 📟 🤚 `username` & `password`
+
+🔜 ➡️ ⚙️ 🚙 🚚 **FastAPI** 🍵 👉.
+
+### `OAuth2PasswordRequestForm`
+
+🥇, 🗄 `OAuth2PasswordRequestForm`, & ⚙️ ⚫️ 🔗 ⏮️ `Depends` *➡ 🛠️* `/token`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="4 76"
+ {!> ../../../docs_src/security/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="2 74"
+ {!> ../../../docs_src/security/tutorial003_py310.py!}
+ ```
+
+`OAuth2PasswordRequestForm` 🎓 🔗 👈 📣 📨 💪 ⏮️:
+
+* `username`.
+* `password`.
+* 📦 `scope` 🏑 🦏 🎻, ✍ 🎻 🎏 🚀.
+* 📦 `grant_type`.
+
+!!! tip
+ Oauth2️⃣ 🔌 🤙 *🚚* 🏑 `grant_type` ⏮️ 🔧 💲 `password`, ✋️ `OAuth2PasswordRequestForm` 🚫 🛠️ ⚫️.
+
+ 🚥 👆 💪 🛠️ ⚫️, ⚙️ `OAuth2PasswordRequestFormStrict` ↩️ `OAuth2PasswordRequestForm`.
+
+* 📦 `client_id` (👥 🚫 💪 ⚫️ 👆 🖼).
+* 📦 `client_secret` (👥 🚫 💪 ⚫️ 👆 🖼).
+
+!!! info
+ `OAuth2PasswordRequestForm` 🚫 🎁 🎓 **FastAPI** `OAuth2PasswordBearer`.
+
+ `OAuth2PasswordBearer` ⚒ **FastAPI** 💭 👈 ⚫️ 💂♂ ⚖. ⚫️ 🚮 👈 🌌 🗄.
+
+ ✋️ `OAuth2PasswordRequestForm` 🎓 🔗 👈 👆 💪 ✔️ ✍ 👆, ⚖️ 👆 💪 ✔️ 📣 `Form` 🔢 🔗.
+
+ ✋️ ⚫️ ⚠ ⚙️ 💼, ⚫️ 🚚 **FastAPI** 🔗, ⚒ ⚫️ ⏩.
+
+### ⚙️ 📨 💽
+
+!!! tip
+ 👐 🔗 🎓 `OAuth2PasswordRequestForm` 🏆 🚫 ✔️ 🔢 `scope` ⏮️ 📏 🎻 👽 🚀, ↩️, ⚫️ 🔜 ✔️ `scopes` 🔢 ⏮️ ☑ 📇 🎻 🔠 ↔ 📨.
+
+ 👥 🚫 ⚙️ `scopes` 👉 🖼, ✋️ 🛠️ 📤 🚥 👆 💪 ⚫️.
+
+🔜, 🤚 👩💻 📊 ⚪️➡️ (❌) 💽, ⚙️ `username` ⚪️➡️ 📨 🏑.
+
+🚥 📤 🙅♂ ✅ 👩💻, 👥 📨 ❌ 💬 "❌ 🆔 ⚖️ 🔐".
+
+❌, 👥 ⚙️ ⚠ `HTTPException`:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="3 77-79"
+ {!> ../../../docs_src/security/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="1 75-77"
+ {!> ../../../docs_src/security/tutorial003_py310.py!}
+ ```
+
+### ✅ 🔐
+
+👉 ☝ 👥 ✔️ 👩💻 📊 ⚪️➡️ 👆 💽, ✋️ 👥 🚫 ✅ 🔐.
+
+➡️ 🚮 👈 💽 Pydantic `UserInDB` 🏷 🥇.
+
+👆 🔜 🙅 🖊 🔢 🔐,, 👥 🔜 ⚙️ (❌) 🔐 🔁 ⚙️.
+
+🚥 🔐 🚫 🏏, 👥 📨 🎏 ❌.
+
+#### 🔐 🔁
+
+"🔁" ⛓: 🏭 🎚 (🔐 👉 💼) 🔘 🔁 🔢 (🎻) 👈 👀 💖 🙃.
+
+🕐❔ 👆 🚶♀️ ⚫️❔ 🎏 🎚 (⚫️❔ 🎏 🔐) 👆 🤚 ⚫️❔ 🎏 🙃.
+
+✋️ 👆 🚫🔜 🗜 ⚪️➡️ 🙃 🔙 🔐.
+
+##### ⚫️❔ ⚙️ 🔐 🔁
+
+🚥 👆 💽 📎, 🧙♀ 🏆 🚫 ✔️ 👆 👩💻' 🔢 🔐, 🕴#️⃣.
+
+, 🧙♀ 🏆 🚫 💪 🔄 ⚙️ 👈 🎏 🔐 ➕1️⃣ ⚙️ (📚 👩💻 ⚙️ 🎏 🔐 🌐, 👉 🔜 ⚠).
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="80-83"
+ {!> ../../../docs_src/security/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="78-81"
+ {!> ../../../docs_src/security/tutorial003_py310.py!}
+ ```
+
+#### 🔃 `**user_dict`
+
+`UserInDB(**user_dict)` ⛓:
+
+*🚶♀️ 🔑 & 💲 `user_dict` 🔗 🔑-💲 ❌, 🌓:*
+
+```Python
+UserInDB(
+ username = user_dict["username"],
+ email = user_dict["email"],
+ full_name = user_dict["full_name"],
+ disabled = user_dict["disabled"],
+ hashed_password = user_dict["hashed_password"],
+)
+```
+
+!!! info
+ 🌅 🏁 🔑 `**👩💻_ #️⃣ ` ✅ 🔙 [🧾 **➕ 🏷**](../extra-models.md#about-user_indict){.internal-link target=_blank}.
+
+## 📨 🤝
+
+📨 `token` 🔗 🔜 🎻 🎚.
+
+⚫️ 🔜 ✔️ `token_type`. 👆 💼, 👥 ⚙️ "📨" 🤝, 🤝 🆎 🔜 "`bearer`".
+
+& ⚫️ 🔜 ✔️ `access_token`, ⏮️ 🎻 ⚗ 👆 🔐 🤝.
+
+👉 🙅 🖼, 👥 🔜 🍕 😟 & 📨 🎏 `username` 🤝.
+
+!!! tip
+ ⏭ 📃, 👆 🔜 👀 🎰 🔐 🛠️, ⏮️ 🔐 #️⃣ & 🥙 🤝.
+
+ ✋️ 🔜, ➡️ 🎯 🔛 🎯 ℹ 👥 💪.
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="85"
+ {!> ../../../docs_src/security/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="83"
+ {!> ../../../docs_src/security/tutorial003_py310.py!}
+ ```
+
+!!! tip
+ 🔌, 👆 🔜 📨 🎻 ⏮️ `access_token` & `token_type`, 🎏 👉 🖼.
+
+ 👉 🕳 👈 👆 ✔️ 👆 👆 📟, & ⚒ 💭 👆 ⚙️ 📚 🎻 🔑.
+
+ ⚫️ 🌖 🕴 👜 👈 👆 ✔️ 💭 ☑ 👆, 🛠️ ⏮️ 🔧.
+
+ 🎂, **FastAPI** 🍵 ⚫️ 👆.
+
+## ℹ 🔗
+
+🔜 👥 🔜 ℹ 👆 🔗.
+
+👥 💚 🤚 `current_user` *🕴* 🚥 👉 👩💻 🦁.
+
+, 👥 ✍ 🌖 🔗 `get_current_active_user` 👈 🔄 ⚙️ `get_current_user` 🔗.
+
+👯♂️ 👉 🔗 🔜 📨 🇺🇸🔍 ❌ 🚥 👩💻 🚫 🔀, ⚖️ 🚥 🔕.
+
+, 👆 🔗, 👥 🔜 🕴 🤚 👩💻 🚥 👩💻 🔀, ☑ 🔓, & 🦁:
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="58-66 69-72 90"
+ {!> ../../../docs_src/security/tutorial003.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python hl_lines="55-64 67-70 88"
+ {!> ../../../docs_src/security/tutorial003_py310.py!}
+ ```
+
+!!! info
+ 🌖 🎚 `WWW-Authenticate` ⏮️ 💲 `Bearer` 👥 🛬 📥 🍕 🔌.
+
+ 🙆 🇺🇸🔍 (❌) 👔 📟 4️⃣0️⃣1️⃣ "⛔" 🤔 📨 `WWW-Authenticate` 🎚.
+
+ 💼 📨 🤝 (👆 💼), 💲 👈 🎚 🔜 `Bearer`.
+
+ 👆 💪 🤙 🚶 👈 ➕ 🎚 & ⚫️ 🔜 👷.
+
+ ✋️ ⚫️ 🚚 📥 🛠️ ⏮️ 🔧.
+
+ , 📤 5️⃣📆 🧰 👈 ⌛ & ⚙️ ⚫️ (🔜 ⚖️ 🔮) & 👈 💪 ⚠ 👆 ⚖️ 👆 👩💻, 🔜 ⚖️ 🔮.
+
+ 👈 💰 🐩...
+
+## 👀 ⚫️ 🎯
+
+📂 🎓 🩺: http://127.0.0.1:8000/docs.
+
+### 🔓
+
+🖊 "✔" 🔼.
+
+⚙️ 🎓:
+
+👩💻: `johndoe`
+
+🔐: `secret`
+
+
+
+⏮️ 🔗 ⚙️, 👆 🔜 👀 ⚫️ 💖:
+
+
+
+### 🤚 👆 👍 👩💻 💽
+
+🔜 ⚙️ 🛠️ `GET` ⏮️ ➡ `/users/me`.
+
+👆 🔜 🤚 👆 👩💻 📊, 💖:
+
+```JSON
+{
+ "username": "johndoe",
+ "email": "johndoe@example.com",
+ "full_name": "John Doe",
+ "disabled": false,
+ "hashed_password": "fakehashedsecret"
+}
+```
+
+
+
+🚥 👆 🖊 🔒 ℹ & ⏏, & ⤴️ 🔄 🎏 🛠️ 🔄, 👆 🔜 🤚 🇺🇸🔍 4️⃣0️⃣1️⃣ ❌:
+
+```JSON
+{
+ "detail": "Not authenticated"
+}
+```
+
+### 🔕 👩💻
+
+🔜 🔄 ⏮️ 🔕 👩💻, 🔓 ⏮️:
+
+👩💻: `alice`
+
+🔐: `secret2`
+
+& 🔄 ⚙️ 🛠️ `GET` ⏮️ ➡ `/users/me`.
+
+👆 🔜 🤚 "🔕 👩💻" ❌, 💖:
+
+```JSON
+{
+ "detail": "Inactive user"
+}
+```
+
+## 🌃
+
+👆 🔜 ✔️ 🧰 🛠️ 🏁 💂♂ ⚙️ ⚓️ 🔛 `username` & `password` 👆 🛠️.
+
+⚙️ 👫 🧰, 👆 💪 ⚒ 💂♂ ⚙️ 🔗 ⏮️ 🙆 💽 & ⏮️ 🙆 👩💻 ⚖️ 💽 🏷.
+
+🕴 ℹ ❌ 👈 ⚫️ 🚫 🤙 "🔐".
+
+⏭ 📃 👆 🔜 👀 ❔ ⚙️ 🔐 🔐 🔁 🗃 & 🥙 🤝.
diff --git a/docs/em/docs/tutorial/sql-databases.md b/docs/em/docs/tutorial/sql-databases.md
new file mode 100644
index 000000000..9d46c2460
--- /dev/null
+++ b/docs/em/docs/tutorial/sql-databases.md
@@ -0,0 +1,786 @@
+# 🗄 (🔗) 💽
+
+**FastAPI** 🚫 🚚 👆 ⚙️ 🗄 (🔗) 💽.
+
+✋️ 👆 💪 ⚙️ 🙆 🔗 💽 👈 👆 💚.
+
+📥 👥 🔜 👀 🖼 ⚙️ 🇸🇲.
+
+👆 💪 💪 🛠️ ⚫️ 🙆 💽 🐕🦺 🇸🇲, 💖:
+
+* ✳
+* ✳
+* 🗄
+* 🐸
+* 🤸♂ 🗄 💽, ♒️.
+
+👉 🖼, 👥 🔜 ⚙️ **🗄**, ↩️ ⚫️ ⚙️ 👁 📁 & 🐍 ✔️ 🛠️ 🐕🦺. , 👆 💪 📁 👉 🖼 & 🏃 ⚫️.
+
+⏪, 👆 🏭 🈸, 👆 💪 💚 ⚙️ 💽 💽 💖 **✳**.
+
+!!! tip
+ 📤 🛂 🏗 🚂 ⏮️ **FastAPI** & **✳**, 🌐 ⚓️ 🔛 **☁**, 🔌 🕸 & 🌖 🧰: https://github.com/tiangolo/full-stack-fastapi-postgresql
+
+!!! note
+ 👀 👈 📚 📟 🐩 `SQLAlchemy` 📟 👆 🔜 ⚙️ ⏮️ 🙆 🛠️.
+
+ **FastAPI** 🎯 📟 🤪 🕧.
+
+## 🐜
+
+**FastAPI** 👷 ⏮️ 🙆 💽 & 🙆 👗 🗃 💬 💽.
+
+⚠ ⚓ ⚙️ "🐜": "🎚-🔗 🗺" 🗃.
+
+🐜 ✔️ 🧰 🗜 ("*🗺*") 🖖 *🎚* 📟 & 💽 🏓 ("*🔗*").
+
+⏮️ 🐜, 👆 🛎 ✍ 🎓 👈 🎨 🏓 🗄 💽, 🔠 🔢 🎓 🎨 🏓, ⏮️ 📛 & 🆎.
+
+🖼 🎓 `Pet` 💪 🎨 🗄 🏓 `pets`.
+
+& 🔠 *👐* 🎚 👈 🎓 🎨 ⏭ 💽.
+
+🖼 🎚 `orion_cat` (👐 `Pet`) 💪 ✔️ 🔢 `orion_cat.type`, 🏓 `type`. & 💲 👈 🔢 💪, ✅ `"cat"`.
+
+👫 🐜 ✔️ 🧰 ⚒ 🔗 ⚖️ 🔗 🖖 🏓 ⚖️ 👨💼.
+
+👉 🌌, 👆 💪 ✔️ 🔢 `orion_cat.owner` & 👨💼 🔜 🔌 💽 👉 🐶 👨💼, ✊ ⚪️➡️ 🏓 *👨💼*.
+
+, `orion_cat.owner.name` 💪 📛 (⚪️➡️ `name` 🏓 `owners` 🏓) 👉 🐶 👨💼.
+
+⚫️ 💪 ✔️ 💲 💖 `"Arquilian"`.
+
+& 🐜 🔜 🌐 👷 🤚 ℹ ⚪️➡️ 🔗 🏓 *👨💼* 🕐❔ 👆 🔄 🔐 ⚫️ ⚪️➡️ 👆 🐶 🎚.
+
+⚠ 🐜 🖼: ✳-🐜 (🍕 ✳ 🛠️), 🇸🇲 🐜 (🍕 🇸🇲, 🔬 🛠️) & 🏒 (🔬 🛠️), 👪 🎏.
+
+📥 👥 🔜 👀 ❔ 👷 ⏮️ **🇸🇲 🐜**.
+
+🎏 🌌 👆 💪 ⚙️ 🙆 🎏 🐜.
+
+!!! tip
+ 📤 🌓 📄 ⚙️ 🏒 📥 🩺.
+
+## 📁 📊
+
+👫 🖼, ➡️ 💬 👆 ✔️ 📁 📛 `my_super_project` 👈 🔌 🎧-📁 🤙 `sql_app` ⏮️ 📊 💖 👉:
+
+```
+.
+└── sql_app
+ ├── __init__.py
+ ├── crud.py
+ ├── database.py
+ ├── main.py
+ ├── models.py
+ └── schemas.py
+```
+
+📁 `__init__.py` 🛁 📁, ✋️ ⚫️ 💬 🐍 👈 `sql_app` ⏮️ 🌐 🚮 🕹 (🐍 📁) 📦.
+
+🔜 ➡️ 👀 ⚫️❔ 🔠 📁/🕹 🔨.
+
+## ❎ `SQLAlchemy`
+
+🥇 👆 💪 ❎ `SQLAlchemy`:
+
+
+
+## 🔗 ⏮️ 💽 🔗
+
+🚥 👆 💚 🔬 🗄 💽 (📁) 🔗, ➡ FastAPI, ℹ 🚮 🎚, 🚮 🏓, 🏓, ⏺, 🔀 📊, ♒️. 👆 💪 ⚙️ 💽 🖥 🗄.
+
+⚫️ 🔜 👀 💖 👉:
+
+
+
+👆 💪 ⚙️ 💳 🗄 🖥 💖 🗄 📋 ⚖️ ExtendsClass.
+
+## 🎛 💽 🎉 ⏮️ 🛠️
+
+🚥 👆 💪 🚫 ⚙️ 🔗 ⏮️ `yield` - 🖼, 🚥 👆 🚫 ⚙️ **🐍 3️⃣.7️⃣** & 💪 🚫 ❎ "🐛" 🤔 🔛 **🐍 3️⃣.6️⃣** - 👆 💪 ⚒ 🆙 🎉 "🛠️" 🎏 🌌.
+
+"🛠️" 🌖 🔢 👈 🕧 🛠️ 🔠 📨, ⏮️ 📟 🛠️ ⏭, & 📟 🛠️ ⏮️ 🔗 🔢.
+
+### ✍ 🛠️
+
+🛠️ 👥 🔜 🚮 (🔢) 🔜 ✍ 🆕 🇸🇲 `SessionLocal` 🔠 📨, 🚮 ⚫️ 📨 & ⤴️ 🔐 ⚫️ 🕐 📨 🏁.
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python hl_lines="14-22"
+ {!> ../../../docs_src/sql_databases/sql_app/alt_main.py!}
+ ```
+
+=== "🐍 3️⃣.9️⃣ & 🔛"
+
+ ```Python hl_lines="12-20"
+ {!> ../../../docs_src/sql_databases/sql_app_py39/alt_main.py!}
+ ```
+
+!!! info
+ 👥 🚮 🏗 `SessionLocal()` & 🚚 📨 `try` 🍫.
+
+ & ⤴️ 👥 🔐 ⚫️ `finally` 🍫.
+
+ 👉 🌌 👥 ⚒ 💭 💽 🎉 🕧 📪 ⏮️ 📨. 🚥 📤 ⚠ ⏪ 🏭 📨.
+
+### 🔃 `request.state`
+
+`request.state` 🏠 🔠 `Request` 🎚. ⚫️ 📤 🏪 ❌ 🎚 📎 📨 ⚫️, 💖 💽 🎉 👉 💼. 👆 💪 ✍ 🌅 🔃 ⚫️ 💃 🩺 🔃 `Request` 🇵🇸.
+
+👥 👉 💼, ⚫️ ℹ 👥 🚚 👁 💽 🎉 ⚙️ 🔘 🌐 📨, & ⤴️ 🔐 ⏮️ (🛠️).
+
+### 🔗 ⏮️ `yield` ⚖️ 🛠️
+
+❎ **🛠️** 📥 🎏 ⚫️❔ 🔗 ⏮️ `yield` 🔨, ⏮️ 🔺:
+
+* ⚫️ 🚚 🌖 📟 & 👄 🌅 🏗.
+* 🛠️ ✔️ `async` 🔢.
+ * 🚥 📤 📟 ⚫️ 👈 ✔️ "⌛" 🕸, ⚫️ 💪 "🍫" 👆 🈸 📤 & 📉 🎭 🍖.
+ * 👐 ⚫️ 🎲 🚫 📶 ⚠ 📥 ⏮️ 🌌 `SQLAlchemy` 👷.
+ * ✋️ 🚥 👆 🚮 🌖 📟 🛠️ 👈 ✔️ 📚 👤/🅾 ⌛, ⚫️ 💪 ⤴️ ⚠.
+* 🛠️ 🏃 *🔠* 📨.
+ * , 🔗 🔜 ✍ 🔠 📨.
+ * 🕐❔ *➡ 🛠️* 👈 🍵 👈 📨 🚫 💪 💽.
+
+!!! tip
+ ⚫️ 🎲 👍 ⚙️ 🔗 ⏮️ `yield` 🕐❔ 👫 🥃 ⚙️ 💼.
+
+!!! info
+ 🔗 ⏮️ `yield` 🚮 ⏳ **FastAPI**.
+
+ ⏮️ ⏬ 👉 🔰 🕴 ✔️ 🖼 ⏮️ 🛠️ & 📤 🎲 📚 🈸 ⚙️ 🛠️ 💽 🎉 🧾.
diff --git a/docs/em/docs/tutorial/static-files.md b/docs/em/docs/tutorial/static-files.md
new file mode 100644
index 000000000..6090c5338
--- /dev/null
+++ b/docs/em/docs/tutorial/static-files.md
@@ -0,0 +1,39 @@
+# 🎻 📁
+
+👆 💪 🍦 🎻 📁 🔁 ⚪️➡️ 📁 ⚙️ `StaticFiles`.
+
+## ⚙️ `StaticFiles`
+
+* 🗄 `StaticFiles`.
+* "🗻" `StaticFiles()` 👐 🎯 ➡.
+
+```Python hl_lines="2 6"
+{!../../../docs_src/static_files/tutorial001.py!}
+```
+
+!!! note "📡 ℹ"
+ 👆 💪 ⚙️ `from starlette.staticfiles import StaticFiles`.
+
+ **FastAPI** 🚚 🎏 `starlette.staticfiles` `fastapi.staticfiles` 🏪 👆, 👩💻. ✋️ ⚫️ 🤙 👟 🔗 ⚪️➡️ 💃.
+
+### ⚫️❔ "🗜"
+
+"🗜" ⛓ ❎ 🏁 "🔬" 🈸 🎯 ➡, 👈 ⤴️ ✊ 💅 🚚 🌐 🎧-➡.
+
+👉 🎏 ⚪️➡️ ⚙️ `APIRouter` 🗻 🈸 🍕 🔬. 🗄 & 🩺 ⚪️➡️ 👆 👑 🈸 🏆 🚫 🔌 🕳 ⚪️➡️ 🗻 🈸, ♒️.
+
+👆 💪 ✍ 🌅 🔃 👉 **🏧 👩💻 🦮**.
+
+## ℹ
+
+🥇 `"/static"` 🔗 🎧-➡ 👉 "🎧-🈸" 🔜 "🗻" 🔛. , 🙆 ➡ 👈 ▶️ ⏮️ `"/static"` 🔜 🍵 ⚫️.
+
+`directory="static"` 🔗 📛 📁 👈 🔌 👆 🎻 📁.
+
+`name="static"` 🤝 ⚫️ 📛 👈 💪 ⚙️ 🔘 **FastAPI**.
+
+🌐 👫 🔢 💪 🎏 🌘 "`static`", 🔆 👫 ⏮️ 💪 & 🎯 ℹ 👆 👍 🈸.
+
+## 🌅 ℹ
+
+🌖 ℹ & 🎛 ✅ 💃 🩺 🔃 🎻 📁.
diff --git a/docs/em/docs/tutorial/testing.md b/docs/em/docs/tutorial/testing.md
new file mode 100644
index 000000000..999d67cd3
--- /dev/null
+++ b/docs/em/docs/tutorial/testing.md
@@ -0,0 +1,188 @@
+# 🔬
+
+👏 💃, 🔬 **FastAPI** 🈸 ⏩ & 😌.
+
+⚫️ ⚓️ 🔛 🇸🇲, ❔ 🔄 🏗 ⚓️ 🔛 📨, ⚫️ 📶 😰 & 🏋️.
+
+⏮️ ⚫️, 👆 💪 ⚙️ ✳ 🔗 ⏮️ **FastAPI**.
+
+## ⚙️ `TestClient`
+
+!!! info
+ ⚙️ `TestClient`, 🥇 ❎ `httpx`.
+
+ 🤶 Ⓜ. `pip install httpx`.
+
+🗄 `TestClient`.
+
+✍ `TestClient` 🚶♀️ 👆 **FastAPI** 🈸 ⚫️.
+
+✍ 🔢 ⏮️ 📛 👈 ▶️ ⏮️ `test_` (👉 🐩 `pytest` 🏛).
+
+⚙️ `TestClient` 🎚 🎏 🌌 👆 ⏮️ `httpx`.
+
+✍ 🙅 `assert` 📄 ⏮️ 🐩 🐍 🧬 👈 👆 💪 ✅ (🔄, 🐩 `pytest`).
+
+```Python hl_lines="2 12 15-18"
+{!../../../docs_src/app_testing/tutorial001.py!}
+```
+
+!!! tip
+ 👀 👈 🔬 🔢 😐 `def`, 🚫 `async def`.
+
+ & 🤙 👩💻 😐 🤙, 🚫 ⚙️ `await`.
+
+ 👉 ✔ 👆 ⚙️ `pytest` 🔗 🍵 🤢.
+
+!!! note "📡 ℹ"
+ 👆 💪 ⚙️ `from starlette.testclient import TestClient`.
+
+ **FastAPI** 🚚 🎏 `starlette.testclient` `fastapi.testclient` 🏪 👆, 👩💻. ✋️ ⚫️ 👟 🔗 ⚪️➡️ 💃.
+
+!!! tip
+ 🚥 👆 💚 🤙 `async` 🔢 👆 💯 ↖️ ⚪️➡️ 📨 📨 👆 FastAPI 🈸 (✅ 🔁 💽 🔢), ✔️ 👀 [🔁 💯](../advanced/async-tests.md){.internal-link target=_blank} 🏧 🔰.
+
+## 🎏 💯
+
+🎰 🈸, 👆 🎲 🔜 ✔️ 👆 💯 🎏 📁.
+
+& 👆 **FastAPI** 🈸 5️⃣📆 ✍ 📚 📁/🕹, ♒️.
+
+### **FastAPI** 📱 📁
+
+➡️ 💬 👆 ✔️ 📁 📊 🔬 [🦏 🈸](./bigger-applications.md){.internal-link target=_blank}:
+
+```
+.
+├── app
+│ ├── __init__.py
+│ └── main.py
+```
+
+📁 `main.py` 👆 ✔️ 👆 **FastAPI** 📱:
+
+
+```Python
+{!../../../docs_src/app_testing/main.py!}
+```
+
+### 🔬 📁
+
+⤴️ 👆 💪 ✔️ 📁 `test_main.py` ⏮️ 👆 💯. ⚫️ 💪 🖖 🔛 🎏 🐍 📦 (🎏 📁 ⏮️ `__init__.py` 📁):
+
+``` hl_lines="5"
+.
+├── app
+│ ├── __init__.py
+│ ├── main.py
+│ └── test_main.py
+```
+
+↩️ 👉 📁 🎏 📦, 👆 💪 ⚙️ ⚖ 🗄 🗄 🎚 `app` ⚪️➡️ `main` 🕹 (`main.py`):
+
+```Python hl_lines="3"
+{!../../../docs_src/app_testing/test_main.py!}
+```
+
+...& ✔️ 📟 💯 💖 ⏭.
+
+## 🔬: ↔ 🖼
+
+🔜 ➡️ ↔ 👉 🖼 & 🚮 🌖 ℹ 👀 ❔ 💯 🎏 🍕.
+
+### ↔ **FastAPI** 📱 📁
+
+➡️ 😣 ⏮️ 🎏 📁 📊 ⏭:
+
+```
+.
+├── app
+│ ├── __init__.py
+│ ├── main.py
+│ └── test_main.py
+```
+
+➡️ 💬 👈 🔜 📁 `main.py` ⏮️ 👆 **FastAPI** 📱 ✔️ 🎏 **➡ 🛠️**.
+
+⚫️ ✔️ `GET` 🛠️ 👈 💪 📨 ❌.
+
+⚫️ ✔️ `POST` 🛠️ 👈 💪 📨 📚 ❌.
+
+👯♂️ *➡ 🛠️* 🚚 `X-Token` 🎚.
+
+=== "🐍 3️⃣.6️⃣ & 🔛"
+
+ ```Python
+ {!> ../../../docs_src/app_testing/app_b/main.py!}
+ ```
+
+=== "🐍 3️⃣.1️⃣0️⃣ & 🔛"
+
+ ```Python
+ {!> ../../../docs_src/app_testing/app_b_py310/main.py!}
+ ```
+
+### ↔ 🔬 📁
+
+👆 💪 ⤴️ ℹ `test_main.py` ⏮️ ↔ 💯:
+
+```Python
+{!> ../../../docs_src/app_testing/app_b/test_main.py!}
+```
+
+🕐❔ 👆 💪 👩💻 🚶♀️ ℹ 📨 & 👆 🚫 💭 ❔, 👆 💪 🔎 (🇺🇸🔍) ❔ ⚫️ `httpx`, ⚖️ ❔ ⚫️ ⏮️ `requests`, 🇸🇲 🔧 ⚓️ 🔛 📨' 🔧.
+
+⤴️ 👆 🎏 👆 💯.
+
+🤶 Ⓜ.:
+
+* 🚶♀️ *➡* ⚖️ *🔢* 🔢, 🚮 ⚫️ 📛 ⚫️.
+* 🚶♀️ 🎻 💪, 🚶♀️ 🐍 🎚 (✅ `dict`) 🔢 `json`.
+* 🚥 👆 💪 📨 *📨 💽* ↩️ 🎻, ⚙️ `data` 🔢 ↩️.
+* 🚶♀️ *🎚*, ⚙️ `dict` `headers` 🔢.
+* *🍪*, `dict` `cookies` 🔢.
+
+🌖 ℹ 🔃 ❔ 🚶♀️ 💽 👩💻 (⚙️ `httpx` ⚖️ `TestClient`) ✅ 🇸🇲 🧾.
+
+!!! info
+ 🗒 👈 `TestClient` 📨 💽 👈 💪 🗜 🎻, 🚫 Pydantic 🏷.
+
+ 🚥 👆 ✔️ Pydantic 🏷 👆 💯 & 👆 💚 📨 🚮 💽 🈸 ⏮️ 🔬, 👆 💪 ⚙️ `jsonable_encoder` 🔬 [🎻 🔗 🔢](encoder.md){.internal-link target=_blank}.
+
+## 🏃 ⚫️
+
+⏮️ 👈, 👆 💪 ❎ `pytest`:
+
+
+Notice that this means "`one_person` is an **instance** of the class `Person`".
+
+It doesn't mean "`one_person` is the **class** called `Person`".
+
## Pydantic models
Pydantic is a Python library to perform data validation.
@@ -436,22 +446,22 @@ And you get all the editor support with that resulting object.
An example from the official Pydantic docs:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python
- {!> ../../../docs_src/python_types/tutorial011.py!}
+ {!> ../../../docs_src/python_types/tutorial011_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python
{!> ../../../docs_src/python_types/tutorial011_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
```Python
- {!> ../../../docs_src/python_types/tutorial011_py310.py!}
+ {!> ../../../docs_src/python_types/tutorial011.py!}
```
!!! info
@@ -464,6 +474,43 @@ You will see a lot more of all this in practice in the [Tutorial - User Guide](t
!!! 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 Required Optional fields.
+## Type Hints with Metadata Annotations
+
+Python also has a feature that allows putting **additional metadata** in these type hints using `Annotated`.
+
+=== "Python 3.9+"
+
+ In Python 3.9, `Annotated` is part of the standard library, so you can import it from `typing`.
+
+ ```Python hl_lines="1 4"
+ {!> ../../../docs_src/python_types/tutorial013_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ In versions below Python 3.9, you import `Annotated` from `typing_extensions`.
+
+ It will already be installed with **FastAPI**.
+
+ ```Python hl_lines="1 4"
+ {!> ../../../docs_src/python_types/tutorial013.py!}
+ ```
+
+Python itself doesn't do anything with this `Annotated`. And for editors and other tools, the type is still `str`.
+
+But you can use this space in `Annotated` to provide **FastAPI** with additional metadata about how you want your application to behave.
+
+The important thing to remember is that **the first *type parameter*** you pass to `Annotated` is the **actual type**. The rest, is just metadata for other tools.
+
+For now, you just need to know that `Annotated` exists, and that it's standard Python. 😎
+
+Later you will see how **powerful** it can be.
+
+!!! tip
+ The fact that this is **standard Python** means that you will still get the **best possible developer experience** in your editor, with the tools you use to analyze and refactor your code, etc. ✨
+
+ And also that your code will be very compatible with many other Python tools and libraries. 🚀
+
## Type hints in **FastAPI**
**FastAPI** takes advantage of these type hints to do several things.
diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md
index 118ee1dc7..dbe3190d8 100644
--- a/docs/en/docs/release-notes.md
+++ b/docs/en/docs/release-notes.md
@@ -3,6 +3,152 @@
## Latest Changes
+## 0.95.1
+
+### Fixes
+
+* 🐛 Fix using `Annotated` in routers or path operations decorated multiple times. PR [#9315](https://github.com/tiangolo/fastapi/pull/9315) by [@sharonyogev](https://github.com/sharonyogev).
+
+### Docs
+
+* 🌐 🔠 📄 🐢 Translate docs to Emoji 🥳 🎉 💥 🤯 🤯. PR [#5385](https://github.com/tiangolo/fastapi/pull/5385) by [@LeeeeT](https://github.com/LeeeeT).
+* 📝 Add notification message warning about old versions of FastAPI not supporting `Annotated`. PR [#9298](https://github.com/tiangolo/fastapi/pull/9298) by [@grdworkin](https://github.com/grdworkin).
+* 📝 Fix typo in `docs/en/docs/advanced/behind-a-proxy.md`. PR [#5681](https://github.com/tiangolo/fastapi/pull/5681) by [@Leommjr](https://github.com/Leommjr).
+* ✏ Fix wrong import from typing module in Persian translations for `docs/fa/docs/index.md`. PR [#6083](https://github.com/tiangolo/fastapi/pull/6083) by [@Kimiaattaei](https://github.com/Kimiaattaei).
+* ✏️ Fix format, remove unnecessary asterisks in `docs/en/docs/help-fastapi.md`. PR [#9249](https://github.com/tiangolo/fastapi/pull/9249) by [@armgabrielyan](https://github.com/armgabrielyan).
+* ✏ Fix typo in `docs/en/docs/tutorial/query-params-str-validations.md`. PR [#9272](https://github.com/tiangolo/fastapi/pull/9272) by [@nicornk](https://github.com/nicornk).
+* ✏ Fix typo/bug in inline code example in `docs/en/docs/tutorial/query-params-str-validations.md`. PR [#9273](https://github.com/tiangolo/fastapi/pull/9273) by [@tim-habitat](https://github.com/tim-habitat).
+* ✏ Fix typo in `docs/en/docs/tutorial/path-params-numeric-validations.md`. PR [#9282](https://github.com/tiangolo/fastapi/pull/9282) by [@aadarsh977](https://github.com/aadarsh977).
+* ✏ Fix typo: 'wll' to 'will' in `docs/en/docs/tutorial/query-params-str-validations.md`. PR [#9380](https://github.com/tiangolo/fastapi/pull/9380) by [@dasstyxx](https://github.com/dasstyxx).
+
+### Translations
+
+* 🌐 Add French translation for `docs/fr/docs/advanced/index.md`. PR [#5673](https://github.com/tiangolo/fastapi/pull/5673) by [@axel584](https://github.com/axel584).
+* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/body-nested-models.md`. PR [#4053](https://github.com/tiangolo/fastapi/pull/4053) by [@luccasmmg](https://github.com/luccasmmg).
+* 🌐 Add Russian translation for `docs/ru/docs/alternatives.md`. PR [#5994](https://github.com/tiangolo/fastapi/pull/5994) by [@Xewus](https://github.com/Xewus).
+* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/extra-models.md`. PR [#5912](https://github.com/tiangolo/fastapi/pull/5912) by [@LorhanSohaky](https://github.com/LorhanSohaky).
+* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/path-operation-configuration.md`. PR [#5936](https://github.com/tiangolo/fastapi/pull/5936) by [@LorhanSohaky](https://github.com/LorhanSohaky).
+* 🌐 Add Russian translation for `docs/ru/docs/contributing.md`. PR [#6002](https://github.com/tiangolo/fastapi/pull/6002) by [@stigsanek](https://github.com/stigsanek).
+* 🌐 Add Korean translation for `docs/tutorial/dependencies/classes-as-dependencies.md`. PR [#9176](https://github.com/tiangolo/fastapi/pull/9176) by [@sehwan505](https://github.com/sehwan505).
+* 🌐 Add Russian translation for `docs/ru/docs/project-generation.md`. PR [#9243](https://github.com/tiangolo/fastapi/pull/9243) by [@Xewus](https://github.com/Xewus).
+* 🌐 Add French translation for `docs/fr/docs/index.md`. PR [#9265](https://github.com/tiangolo/fastapi/pull/9265) by [@frabc](https://github.com/frabc).
+* 🌐 Add Russian translation for `docs/ru/docs/tutorial/query-params-str-validations.md`. PR [#9267](https://github.com/tiangolo/fastapi/pull/9267) by [@dedkot01](https://github.com/dedkot01).
+* 🌐 Add Russian translation for `docs/ru/docs/benchmarks.md`. PR [#9271](https://github.com/tiangolo/fastapi/pull/9271) by [@Xewus](https://github.com/Xewus).
+
+### Internal
+
+* 🔧 Update sponsors: remove Jina. PR [#9388](https://github.com/tiangolo/fastapi/pull/9388) by [@tiangolo](https://github.com/tiangolo).
+* 🔧 Update sponsors, add databento, remove Ines's course and StriveWorks. PR [#9351](https://github.com/tiangolo/fastapi/pull/9351) by [@tiangolo](https://github.com/tiangolo).
+
+## 0.95.0
+
+### Highlights
+
+This release adds support for dependencies and parameters using `Annotated` and recommends its usage. ✨
+
+This has **several benefits**, one of the main ones is that now the parameters of your functions with `Annotated` would **not be affected** at all.
+
+If you call those functions in **other places in your code**, the actual **default values** will be kept, your editor will help you notice missing **required arguments**, Python will require you to pass required arguments at **runtime**, you will be able to **use the same functions** for different things and with different libraries (e.g. **Typer** will soon support `Annotated` too, then you could use the same function for an API and a CLI), etc.
+
+Because `Annotated` is **standard Python**, you still get all the **benefits** from editors and tools, like **autocompletion**, **inline errors**, etc.
+
+One of the **biggest benefits** is that now you can create `Annotated` dependencies that are then shared by multiple *path operation functions*, this will allow you to **reduce** a lot of **code duplication** in your codebase, while keeping all the support from editors and tools.
+
+For example, you could have code like this:
+
+```Python
+def get_current_user(token: str):
+ # authenticate user
+ return User()
+
+
+@app.get("/items/")
+def read_items(user: User = Depends(get_current_user)):
+ ...
+
+
+@app.post("/items/")
+def create_item(*, user: User = Depends(get_current_user), item: Item):
+ ...
+
+
+@app.get("/items/{item_id}")
+def read_item(*, user: User = Depends(get_current_user), item_id: int):
+ ...
+
+
+@app.delete("/items/{item_id}")
+def delete_item(*, user: User = Depends(get_current_user), item_id: int):
+ ...
+```
+
+There's a bit of code duplication for the dependency:
+
+```Python
+user: User = Depends(get_current_user)
+```
+
+...the bigger the codebase, the more noticeable it is.
+
+Now you can create an annotated dependency once, like this:
+
+```Python
+CurrentUser = Annotated[User, Depends(get_current_user)]
+```
+
+And then you can reuse this `Annotated` dependency:
+
+```Python
+CurrentUser = Annotated[User, Depends(get_current_user)]
+
+
+@app.get("/items/")
+def read_items(user: CurrentUser):
+ ...
+
+
+@app.post("/items/")
+def create_item(user: CurrentUser, item: Item):
+ ...
+
+
+@app.get("/items/{item_id}")
+def read_item(user: CurrentUser, item_id: int):
+ ...
+
+
+@app.delete("/items/{item_id}")
+def delete_item(user: CurrentUser, item_id: int):
+ ...
+```
+
+...and `CurrentUser` has all the typing information as `User`, so your editor will work as expected (autocompletion and everything), and **FastAPI** will be able to understand the dependency defined in `Annotated`. 😎
+
+Roughly **all the docs** have been rewritten to use `Annotated` as the main way to declare **parameters** and **dependencies**. All the **examples** in the docs now include a version with `Annotated` and a version without it, for each of the specific Python versions (when there are small differences/improvements in more recent versions). There were around 23K new lines added between docs, examples, and tests. 🚀
+
+The key updated docs are:
+
+* Python Types Intro:
+ * [Type Hints with Metadata Annotations](https://fastapi.tiangolo.com/python-types/#type-hints-with-metadata-annotations).
+* Tutorial:
+ * [Query Parameters and String Validations - Additional validation](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#additional-validation)
+ * [Advantages of `Annotated`](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#advantages-of-annotated)
+ * [Path Parameters and Numeric Validations - Order the parameters as you need, tricks](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#order-the-parameters-as-you-need-tricks)
+ * [Better with `Annotated`](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#better-with-annotated)
+ * [Dependencies - First Steps - Share `Annotated` dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/#share-annotated-dependencies)
+
+Special thanks to [@nzig](https://github.com/nzig) for the core implementation and to [@adriangb](https://github.com/adriangb) for the inspiration and idea with [Xpresso](https://github.com/adriangb/xpresso)! 🚀
+
+### Features
+
+* ✨Add support for PEP-593 `Annotated` for specifying dependencies and parameters. PR [#4871](https://github.com/tiangolo/fastapi/pull/4871) by [@nzig](https://github.com/nzig).
+
+### Docs
+
+* 📝 Tweak tip recommending `Annotated` in docs. PR [#9270](https://github.com/tiangolo/fastapi/pull/9270) by [@tiangolo](https://github.com/tiangolo).
+* 📝 Update order of examples, latest Python version first, and simplify version tab names. PR [#9269](https://github.com/tiangolo/fastapi/pull/9269) by [@tiangolo](https://github.com/tiangolo).
+* 📝 Update all docs to use `Annotated` as the main recommendation, with new examples and tests. PR [#9268](https://github.com/tiangolo/fastapi/pull/9268) by [@tiangolo](https://github.com/tiangolo).
+
## 0.94.1
### Fixes
diff --git a/docs/en/docs/tutorial/background-tasks.md b/docs/en/docs/tutorial/background-tasks.md
index 191a4ca0f..178297192 100644
--- a/docs/en/docs/tutorial/background-tasks.md
+++ b/docs/en/docs/tutorial/background-tasks.md
@@ -57,18 +57,42 @@ Using `BackgroundTasks` also works with the dependency injection system, you can
**FastAPI** knows what to do in each case and how to re-use the same object, so that all the background tasks are merged together and are run in the background afterwards:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="13 15 22 25"
- {!> ../../../docs_src/background_tasks/tutorial002.py!}
+ {!> ../../../docs_src/background_tasks/tutorial002_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="13 15 22 25"
+ {!> ../../../docs_src/background_tasks/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="14 16 23 26"
+ {!> ../../../docs_src/background_tasks/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="11 13 20 23"
{!> ../../../docs_src/background_tasks/tutorial002_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="13 15 22 25"
+ {!> ../../../docs_src/background_tasks/tutorial002.py!}
+ ```
+
In this example, the messages will be written to the `log.txt` file *after* the response is sent.
If there was a query in the request, it will be written to the log in a background task.
diff --git a/docs/en/docs/tutorial/bigger-applications.md b/docs/en/docs/tutorial/bigger-applications.md
index 1de05a00a..daa7353a2 100644
--- a/docs/en/docs/tutorial/bigger-applications.md
+++ b/docs/en/docs/tutorial/bigger-applications.md
@@ -112,9 +112,26 @@ So we put them in their own `dependencies` module (`app/dependencies.py`).
We will now use a simple dependency to read a custom `X-Token` header:
-```Python hl_lines="1 4-6"
-{!../../../docs_src/bigger_applications/app/dependencies.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="3 6-8"
+ {!> ../../../docs_src/bigger_applications/app_an_py39/dependencies.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 5-7"
+ {!> ../../../docs_src/bigger_applications/app_an/dependencies.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="1 4-6"
+ {!> ../../../docs_src/bigger_applications/app/dependencies.py!}
+ ```
!!! tip
We are using an invented header to simplify this example.
diff --git a/docs/en/docs/tutorial/body-fields.md b/docs/en/docs/tutorial/body-fields.md
index 0cfe576d6..8966032ff 100644
--- a/docs/en/docs/tutorial/body-fields.md
+++ b/docs/en/docs/tutorial/body-fields.md
@@ -6,18 +6,42 @@ The same way you can declare additional validation and metadata in *path operati
First, you have to import it:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="4"
- {!> ../../../docs_src/body_fields/tutorial001.py!}
+ {!> ../../../docs_src/body_fields/tutorial001_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body_fields/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body_fields/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="2"
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body_fields/tutorial001.py!}
+ ```
+
!!! warning
Notice that `Field` is imported directly from `pydantic`, not from `fastapi` as are all the rest (`Query`, `Path`, `Body`, etc).
@@ -25,18 +49,42 @@ First, you have to import it:
You can then use `Field` with model attributes:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="11-14"
- {!> ../../../docs_src/body_fields/tutorial001.py!}
+ {!> ../../../docs_src/body_fields/tutorial001_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="11-14"
+ {!> ../../../docs_src/body_fields/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="12-15"
+ {!> ../../../docs_src/body_fields/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="9-12"
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="11-14"
+ {!> ../../../docs_src/body_fields/tutorial001.py!}
+ ```
+
`Field` works the same way as `Query`, `Path` and `Body`, it has all the same parameters, etc.
!!! note "Technical Details"
diff --git a/docs/en/docs/tutorial/body-multiple-params.md b/docs/en/docs/tutorial/body-multiple-params.md
index 31dd27fed..b214092c9 100644
--- a/docs/en/docs/tutorial/body-multiple-params.md
+++ b/docs/en/docs/tutorial/body-multiple-params.md
@@ -8,18 +8,42 @@ First, of course, you can mix `Path`, `Query` and request body parameter declara
And you can also declare body parameters as optional, by setting the default to `None`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="19-21"
- {!> ../../../docs_src/body_multiple_params/tutorial001.py!}
+ ```Python hl_lines="18-20"
+ {!> ../../../docs_src/body_multiple_params/tutorial001_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="18-20"
+ {!> ../../../docs_src/body_multiple_params/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="19-21"
+ {!> ../../../docs_src/body_multiple_params/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="17-19"
{!> ../../../docs_src/body_multiple_params/tutorial001_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="19-21"
+ {!> ../../../docs_src/body_multiple_params/tutorial001.py!}
+ ```
+
!!! note
Notice that, in this case, the `item` that would be taken from the body is optional. As it has a `None` default value.
@@ -38,18 +62,18 @@ In the previous example, the *path operations* would expect a JSON body with the
But you can also declare multiple body parameters, e.g. `item` and `user`:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="22"
- {!> ../../../docs_src/body_multiple_params/tutorial002.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="20"
{!> ../../../docs_src/body_multiple_params/tutorial002_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/body_multiple_params/tutorial002.py!}
+ ```
+
In this case, **FastAPI** will notice that there are more than one body parameters in the function (two parameters that are Pydantic models).
So, it will then use the parameter names as keys (field names) in the body, and expect a body like:
@@ -87,18 +111,42 @@ If you declare it as is, because it is a singular value, **FastAPI** will assume
But you can instruct **FastAPI** to treat it as another body key using `Body`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="22"
- {!> ../../../docs_src/body_multiple_params/tutorial003.py!}
+ ```Python hl_lines="23"
+ {!> ../../../docs_src/body_multiple_params/tutorial003_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="23"
+ {!> ../../../docs_src/body_multiple_params/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/body_multiple_params/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="20"
{!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/body_multiple_params/tutorial003.py!}
+ ```
+
In this case, **FastAPI** will expect a body like:
```JSON
@@ -137,18 +185,42 @@ q: str | None = None
For example:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
+
+ ```Python hl_lines="27"
+ {!> ../../../docs_src/body_multiple_params/tutorial004_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="27"
+ {!> ../../../docs_src/body_multiple_params/tutorial004_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="28"
+ {!> ../../../docs_src/body_multiple_params/tutorial004_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="25"
+ {!> ../../../docs_src/body_multiple_params/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="27"
{!> ../../../docs_src/body_multiple_params/tutorial004.py!}
```
-=== "Python 3.10 and above"
-
- ```Python hl_lines="26"
- {!> ../../../docs_src/body_multiple_params/tutorial004_py310.py!}
- ```
-
!!! info
`Body` also has all the same extra validation and metadata parameters as `Query`,`Path` and others you will see later.
@@ -166,18 +238,42 @@ item: Item = Body(embed=True)
as in:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="17"
- {!> ../../../docs_src/body_multiple_params/tutorial005.py!}
+ {!> ../../../docs_src/body_multiple_params/tutorial005_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/body_multiple_params/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body_multiple_params/tutorial005_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="15"
{!> ../../../docs_src/body_multiple_params/tutorial005_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/body_multiple_params/tutorial005.py!}
+ ```
+
In this case **FastAPI** will expect a body like:
```JSON hl_lines="2"
diff --git a/docs/en/docs/tutorial/body-nested-models.md b/docs/en/docs/tutorial/body-nested-models.md
index d51f171d6..ffa0c0d0e 100644
--- a/docs/en/docs/tutorial/body-nested-models.md
+++ b/docs/en/docs/tutorial/body-nested-models.md
@@ -6,18 +6,18 @@ With **FastAPI**, you can define, validate, document, and use arbitrarily deeply
You can define an attribute to be a subtype. For example, a Python `list`:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="14"
- {!> ../../../docs_src/body_nested_models/tutorial001.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="12"
{!> ../../../docs_src/body_nested_models/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/body_nested_models/tutorial001.py!}
+ ```
+
This will make `tags` be a list, although it doesn't declare the type of the elements of the list.
## List fields with type parameter
@@ -61,22 +61,22 @@ Use that same standard syntax for model attributes with internal types.
So, in our example, we can make `tags` be specifically a "list of strings":
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="14"
- {!> ../../../docs_src/body_nested_models/tutorial002.py!}
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/body_nested_models/tutorial002_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial002_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="12"
- {!> ../../../docs_src/body_nested_models/tutorial002_py310.py!}
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/body_nested_models/tutorial002.py!}
```
## Set types
@@ -87,22 +87,22 @@ And Python has a special data type for sets of unique items, the `set`.
Then we can declare `tags` as a set of strings:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="1 14"
- {!> ../../../docs_src/body_nested_models/tutorial003.py!}
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/body_nested_models/tutorial003_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial003_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="12"
- {!> ../../../docs_src/body_nested_models/tutorial003_py310.py!}
+ ```Python hl_lines="1 14"
+ {!> ../../../docs_src/body_nested_models/tutorial003.py!}
```
With this, even if you receive a request with duplicate data, it will be converted to a set of unique items.
@@ -125,44 +125,44 @@ All that, arbitrarily nested.
For example, we can define an `Image` model:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="9-11"
- {!> ../../../docs_src/body_nested_models/tutorial004.py!}
+ ```Python hl_lines="7-9"
+ {!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="9-11"
{!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="7-9"
- {!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
+ ```Python hl_lines="9-11"
+ {!> ../../../docs_src/body_nested_models/tutorial004.py!}
```
### Use the submodel as a type
And then we can use it as the type of an attribute:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="20"
- {!> ../../../docs_src/body_nested_models/tutorial004.py!}
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="18"
- {!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_nested_models/tutorial004.py!}
```
This would mean that **FastAPI** would expect a body similar to:
@@ -196,22 +196,22 @@ To see all the options you have, checkout the docs for ../../../docs_src/body_nested_models/tutorial005.py!}
+ ```Python hl_lines="2 8"
+ {!> ../../../docs_src/body_nested_models/tutorial005_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="4 10"
{!> ../../../docs_src/body_nested_models/tutorial005_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="2 8"
- {!> ../../../docs_src/body_nested_models/tutorial005_py310.py!}
+ ```Python hl_lines="4 10"
+ {!> ../../../docs_src/body_nested_models/tutorial005.py!}
```
The string will be checked to be a valid URL, and documented in JSON Schema / OpenAPI as such.
@@ -220,22 +220,22 @@ The string will be checked to be a valid URL, and documented in JSON Schema / Op
You can also use Pydantic models as subtypes of `list`, `set`, etc:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="20"
- {!> ../../../docs_src/body_nested_models/tutorial006.py!}
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body_nested_models/tutorial006_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial006_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="18"
- {!> ../../../docs_src/body_nested_models/tutorial006_py310.py!}
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_nested_models/tutorial006.py!}
```
This will expect (convert, validate, document, etc) a JSON body like:
@@ -271,22 +271,22 @@ This will expect (convert, validate, document, etc) a JSON body like:
You can define arbitrarily deeply nested models:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="9 14 20 23 27"
- {!> ../../../docs_src/body_nested_models/tutorial007.py!}
+ ```Python hl_lines="7 12 18 21 25"
+ {!> ../../../docs_src/body_nested_models/tutorial007_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="9 14 20 23 27"
{!> ../../../docs_src/body_nested_models/tutorial007_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="7 12 18 21 25"
- {!> ../../../docs_src/body_nested_models/tutorial007_py310.py!}
+ ```Python hl_lines="9 14 20 23 27"
+ {!> ../../../docs_src/body_nested_models/tutorial007.py!}
```
!!! info
@@ -308,18 +308,18 @@ images: list[Image]
as in:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="15"
- {!> ../../../docs_src/body_nested_models/tutorial008.py!}
- ```
-
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="13"
{!> ../../../docs_src/body_nested_models/tutorial008_py39.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="15"
+ {!> ../../../docs_src/body_nested_models/tutorial008.py!}
+ ```
+
## Editor support everywhere
And you get editor support everywhere.
@@ -348,18 +348,18 @@ That's what we are going to see here.
In this case, you would accept any `dict` as long as it has `int` keys with `float` values:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="9"
- {!> ../../../docs_src/body_nested_models/tutorial009.py!}
- ```
-
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="7"
{!> ../../../docs_src/body_nested_models/tutorial009_py39.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/body_nested_models/tutorial009.py!}
+ ```
+
!!! tip
Have in mind that JSON only supports `str` as keys.
diff --git a/docs/en/docs/tutorial/body-updates.md b/docs/en/docs/tutorial/body-updates.md
index 7d8675060..a32948db1 100644
--- a/docs/en/docs/tutorial/body-updates.md
+++ b/docs/en/docs/tutorial/body-updates.md
@@ -6,22 +6,22 @@ To update an item you can use the ../../../docs_src/body_updates/tutorial001.py!}
+ ```Python hl_lines="28-33"
+ {!> ../../../docs_src/body_updates/tutorial001_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="30-35"
{!> ../../../docs_src/body_updates/tutorial001_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="28-33"
- {!> ../../../docs_src/body_updates/tutorial001_py310.py!}
+ ```Python hl_lines="30-35"
+ {!> ../../../docs_src/body_updates/tutorial001.py!}
```
`PUT` is used to receive data that should replace the existing data.
@@ -67,22 +67,22 @@ That would generate a `dict` with only the data that was set when creating the `
Then you can use this to generate a `dict` with only the data that was set (sent in the request), omitting default values:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="34"
- {!> ../../../docs_src/body_updates/tutorial002.py!}
+ ```Python hl_lines="32"
+ {!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="34"
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="32"
- {!> ../../../docs_src/body_updates/tutorial002_py310.py!}
+ ```Python hl_lines="34"
+ {!> ../../../docs_src/body_updates/tutorial002.py!}
```
### Using Pydantic's `update` parameter
@@ -91,22 +91,22 @@ Now, you can create a copy of the existing model using `.copy()`, and pass the `
Like `stored_item_model.copy(update=update_data)`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="35"
- {!> ../../../docs_src/body_updates/tutorial002.py!}
+ ```Python hl_lines="33"
+ {!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="35"
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="33"
- {!> ../../../docs_src/body_updates/tutorial002_py310.py!}
+ ```Python hl_lines="35"
+ {!> ../../../docs_src/body_updates/tutorial002.py!}
```
### Partial updates recap
@@ -124,22 +124,22 @@ In summary, to apply partial updates you would:
* Save the data to your DB.
* Return the updated model.
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="30-37"
- {!> ../../../docs_src/body_updates/tutorial002.py!}
+ ```Python hl_lines="28-35"
+ {!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="30-37"
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="28-35"
- {!> ../../../docs_src/body_updates/tutorial002_py310.py!}
+ ```Python hl_lines="30-37"
+ {!> ../../../docs_src/body_updates/tutorial002.py!}
```
!!! tip
diff --git a/docs/en/docs/tutorial/body.md b/docs/en/docs/tutorial/body.md
index 509005936..172b91fdf 100644
--- a/docs/en/docs/tutorial/body.md
+++ b/docs/en/docs/tutorial/body.md
@@ -19,36 +19,36 @@ To declare a **request** body, you use ../../../docs_src/body/tutorial001.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="2"
{!> ../../../docs_src/body/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body/tutorial001.py!}
+ ```
+
## Create your data model
Then you declare your data model as a class that inherits from `BaseModel`.
Use standard Python types for all the attributes:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="7-11"
- {!> ../../../docs_src/body/tutorial001.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="5-9"
{!> ../../../docs_src/body/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="7-11"
+ {!> ../../../docs_src/body/tutorial001.py!}
+ ```
+
The same as when declaring query parameters, when a model attribute has a default value, it is not required. Otherwise, it is required. Use `None` to make it just optional.
For example, this model above declares a JSON "`object`" (or Python `dict`) like:
@@ -75,18 +75,18 @@ For example, this model above declares a JSON "`object`" (or Python `dict`) like
To add it to your *path operation*, declare it the same way you declared path and query parameters:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="18"
- {!> ../../../docs_src/body/tutorial001.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="16"
{!> ../../../docs_src/body/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body/tutorial001.py!}
+ ```
+
...and declare its type as the model you created, `Item`.
## Results
@@ -149,54 +149,54 @@ But you would get the same editor support with ../../../docs_src/body/tutorial002.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="19"
{!> ../../../docs_src/body/tutorial002_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="21"
+ {!> ../../../docs_src/body/tutorial002.py!}
+ ```
+
## Request body + path parameters
You can declare path parameters and request body at the same time.
**FastAPI** will recognize that the function parameters that match path parameters should be **taken from the path**, and that function parameters that are declared to be Pydantic models should be **taken from the request body**.
-=== "Python 3.6 and above"
-
- ```Python hl_lines="17-18"
- {!> ../../../docs_src/body/tutorial003.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="15-16"
{!> ../../../docs_src/body/tutorial003_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="17-18"
+ {!> ../../../docs_src/body/tutorial003.py!}
+ ```
+
## Request body + path + query parameters
You can also declare **body**, **path** and **query** parameters, all at the same time.
**FastAPI** will recognize each of them and take the data from the correct place.
-=== "Python 3.6 and above"
-
- ```Python hl_lines="18"
- {!> ../../../docs_src/body/tutorial004.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="16"
{!> ../../../docs_src/body/tutorial004_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body/tutorial004.py!}
+ ```
+
The function parameters will be recognized as follows:
* If the parameter is also declared in the **path**, it will be used as a path parameter.
diff --git a/docs/en/docs/tutorial/cookie-params.md b/docs/en/docs/tutorial/cookie-params.md
index 221cdfffb..111e93458 100644
--- a/docs/en/docs/tutorial/cookie-params.md
+++ b/docs/en/docs/tutorial/cookie-params.md
@@ -6,36 +6,84 @@ You can define Cookie parameters the same way you define `Query` and `Path` para
First import `Cookie`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="3"
- {!> ../../../docs_src/cookie_params/tutorial001.py!}
+ {!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/cookie_params/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/cookie_params/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="1"
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/cookie_params/tutorial001.py!}
+ ```
+
## Declare `Cookie` parameters
Then declare the cookie parameters using the same structure as with `Path` and `Query`.
The first value is the default value, you can pass all the extra validation or annotation parameters:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="9"
- {!> ../../../docs_src/cookie_params/tutorial001.py!}
+ {!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/cookie_params/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/cookie_params/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/cookie_params/tutorial001.py!}
+ ```
+
!!! note "Technical Details"
`Cookie` is a "sister" class of `Path` and `Query`. It also inherits from the same common `Param` class.
diff --git a/docs/en/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/en/docs/tutorial/dependencies/classes-as-dependencies.md
index fb41ba1f6..498d935fe 100644
--- a/docs/en/docs/tutorial/dependencies/classes-as-dependencies.md
+++ b/docs/en/docs/tutorial/dependencies/classes-as-dependencies.md
@@ -6,18 +6,42 @@ Before diving deeper into the **Dependency Injection** system, let's upgrade the
In the previous example, we were returning a `dict` from our dependency ("dependable"):
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="9"
- {!> ../../../docs_src/dependencies/tutorial001.py!}
+ {!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/dependencies/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
But then we get a `dict` in the parameter `commons` of the *path operation function*.
And we know that editors can't provide a lot of support (like completion) for `dict`s, because they can't know their keys and value types.
@@ -79,46 +103,118 @@ That also applies to callables with no parameters at all. The same as it would b
Then, we can change the dependency "dependable" `common_parameters` from above to the class `CommonQueryParams`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="11-15"
- {!> ../../../docs_src/dependencies/tutorial002.py!}
+ {!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="11-15"
+ {!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="12-16"
+ {!> ../../../docs_src/dependencies/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="9-13"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
-Pay attention to the `__init__` method used to create the instance of the class:
+=== "Python 3.6+ non-Annotated"
-=== "Python 3.6 and above"
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="12"
+ ```Python hl_lines="11-15"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
-=== "Python 3.10 and above"
+Pay attention to the `__init__` method used to create the instance of the class:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/dependencies/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="10"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
-...it has the same parameters as our previous `common_parameters`:
+=== "Python 3.6+ non-Annotated"
-=== "Python 3.6 and above"
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="9"
- {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/dependencies/tutorial002.py!}
```
-=== "Python 3.10 and above"
+...it has the same parameters as our previous `common_parameters`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/dependencies/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="6"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
Those parameters are what **FastAPI** will use to "solve" the dependency.
In both cases, it will have:
@@ -133,32 +229,67 @@ In both cases the data will be converted, validated, documented on the OpenAPI s
Now you can declare your dependency using this class.
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="19"
- {!> ../../../docs_src/dependencies/tutorial002.py!}
+ {!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/dependencies/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial002.py!}
+ ```
+
**FastAPI** calls the `CommonQueryParams` class. This creates an "instance" of that class and the instance will be passed as the parameter `commons` to your function.
## Type annotation vs `Depends`
Notice how we write `CommonQueryParams` twice in the above code:
-```Python
-commons: CommonQueryParams = Depends(CommonQueryParams)
-```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python
+ commons: CommonQueryParams = Depends(CommonQueryParams)
+ ```
+
+=== "Python 3.6+"
+
+ ```Python
+ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
+ ```
The last `CommonQueryParams`, in:
```Python
-... = Depends(CommonQueryParams)
+... Depends(CommonQueryParams)
```
...is what **FastAPI** will actually use to know what is the dependency.
@@ -169,32 +300,78 @@ From it is that FastAPI will extract the declared parameters and that is what Fa
In this case, the first `CommonQueryParams`, in:
-```Python
-commons: CommonQueryParams ...
-```
+=== "Python 3.6+"
-...doesn't have any special meaning for **FastAPI**. FastAPI won't use it for data conversion, validation, etc. (as it is using the `= Depends(CommonQueryParams)` for that).
+ ```Python
+ commons: Annotated[CommonQueryParams, ...
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python
+ commons: CommonQueryParams ...
+ ```
+
+...doesn't have any special meaning for **FastAPI**. FastAPI won't use it for data conversion, validation, etc. (as it is using the `Depends(CommonQueryParams)` for that).
You could actually write just:
-```Python
-commons = Depends(CommonQueryParams)
-```
+=== "Python 3.6+"
+
+ ```Python
+ commons: Annotated[Any, Depends(CommonQueryParams)]
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python
+ commons = Depends(CommonQueryParams)
+ ```
..as in:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="19"
- {!> ../../../docs_src/dependencies/tutorial003.py!}
+ {!> ../../../docs_src/dependencies/tutorial003_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/dependencies/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial003_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial003.py!}
+ ```
+
But declaring the type is encouraged as that way your editor will know what will be passed as the parameter `commons`, and then it can help you with code completion, type checks, etc:
@@ -203,9 +380,20 @@ But declaring the type is encouraged as that way your editor will know what will
But you see that we are having some code repetition here, writing `CommonQueryParams` twice:
-```Python
-commons: CommonQueryParams = Depends(CommonQueryParams)
-```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python
+ commons: CommonQueryParams = Depends(CommonQueryParams)
+ ```
+
+=== "Python 3.6+"
+
+ ```Python
+ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
+ ```
**FastAPI** provides a shortcut for these cases, in where the dependency is *specifically* a class that **FastAPI** will "call" to create an instance of the class itself.
@@ -213,32 +401,78 @@ For those specific cases, you can do the following:
Instead of writing:
-```Python
-commons: CommonQueryParams = Depends(CommonQueryParams)
-```
+=== "Python 3.6+"
+
+ ```Python
+ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python
+ commons: CommonQueryParams = Depends(CommonQueryParams)
+ ```
...you write:
-```Python
-commons: CommonQueryParams = Depends()
-```
+=== "Python 3.6+"
-You declare the dependency as the type of the parameter, and you use `Depends()` as its "default" value (that after the `=`) for that function's parameter, without any parameter in `Depends()`, instead of having to write the full class *again* inside of `Depends(CommonQueryParams)`.
+ ```Python
+ commons: Annotated[CommonQueryParams, Depends()]
+ ```
+
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python
+ commons: CommonQueryParams = Depends()
+ ```
+
+You declare the dependency as the type of the parameter, and you use `Depends()` without any parameter, instead of having to write the full class *again* inside of `Depends(CommonQueryParams)`.
The same example would then look like:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="19"
- {!> ../../../docs_src/dependencies/tutorial004.py!}
+ {!> ../../../docs_src/dependencies/tutorial004_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial004_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/dependencies/tutorial004_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial004_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial004.py!}
+ ```
+
...and **FastAPI** will know what to do.
!!! tip
diff --git a/docs/en/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/en/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md
index a1bbcc6c7..935555339 100644
--- a/docs/en/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md
+++ b/docs/en/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md
@@ -14,9 +14,26 @@ The *path operation decorator* receives an optional argument `dependencies`.
It should be a `list` of `Depends()`:
-```Python hl_lines="17"
-{!../../../docs_src/dependencies/tutorial006.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/dependencies/tutorial006_an.py!}
+ ```
+
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/dependencies/tutorial006.py!}
+ ```
These dependencies will be executed/solved the same way normal dependencies. But their value (if they return any) won't be passed to your *path operation function*.
@@ -40,17 +57,51 @@ You can use the same dependency *functions* you use normally.
They can declare request requirements (like headers) or other sub-dependencies:
-```Python hl_lines="6 11"
-{!../../../docs_src/dependencies/tutorial006.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="8 13"
+ {!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="7 12"
+ {!> ../../../docs_src/dependencies/tutorial006_an.py!}
+ ```
+
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="6 11"
+ {!> ../../../docs_src/dependencies/tutorial006.py!}
+ ```
### Raise exceptions
These dependencies can `raise` exceptions, the same as normal dependencies:
-```Python hl_lines="8 13"
-{!../../../docs_src/dependencies/tutorial006.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="10 15"
+ {!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 14"
+ {!> ../../../docs_src/dependencies/tutorial006_an.py!}
+ ```
+
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="8 13"
+ {!> ../../../docs_src/dependencies/tutorial006.py!}
+ ```
### Return values
@@ -58,9 +109,26 @@ And they can return values or not, the values won't be used.
So, you can re-use a normal dependency (that returns a value) you already use somewhere else, and even though the value won't be used, the dependency will be executed:
-```Python hl_lines="9 14"
-{!../../../docs_src/dependencies/tutorial006.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="11 16"
+ {!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10 15"
+ {!> ../../../docs_src/dependencies/tutorial006_an.py!}
+ ```
+
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9 14"
+ {!> ../../../docs_src/dependencies/tutorial006.py!}
+ ```
## Dependencies for a group of *path operations*
diff --git a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md
index a7300f0b7..8a5422ac8 100644
--- a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md
+++ b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md
@@ -66,9 +66,26 @@ You can have sub-dependencies and "trees" of sub-dependencies of any size and sh
For example, `dependency_c` can have a dependency on `dependency_b`, and `dependency_b` on `dependency_a`:
-```Python hl_lines="4 12 20"
-{!../../../docs_src/dependencies/tutorial008.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="6 14 22"
+ {!> ../../../docs_src/dependencies/tutorial008_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="5 13 21"
+ {!> ../../../docs_src/dependencies/tutorial008_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="4 12 20"
+ {!> ../../../docs_src/dependencies/tutorial008.py!}
+ ```
And all of them can use `yield`.
@@ -76,9 +93,26 @@ In this case `dependency_c`, to execute its exit code, needs the value from `dep
And, in turn, `dependency_b` needs the value from `dependency_a` (here named `dep_a`) to be available for its exit code.
-```Python hl_lines="16-17 24-25"
-{!../../../docs_src/dependencies/tutorial008.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="18-19 26-27"
+ {!> ../../../docs_src/dependencies/tutorial008_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="17-18 25-26"
+ {!> ../../../docs_src/dependencies/tutorial008_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="16-17 24-25"
+ {!> ../../../docs_src/dependencies/tutorial008.py!}
+ ```
The same way, you could have dependencies with `yield` and `return` mixed.
diff --git a/docs/en/docs/tutorial/dependencies/global-dependencies.md b/docs/en/docs/tutorial/dependencies/global-dependencies.md
index bcd61d52b..0989b31d4 100644
--- a/docs/en/docs/tutorial/dependencies/global-dependencies.md
+++ b/docs/en/docs/tutorial/dependencies/global-dependencies.md
@@ -6,9 +6,26 @@ Similar to the way you can [add `dependencies` to the *path operation decorators
In that case, they will be applied to all the *path operations* in the application:
-```Python hl_lines="15"
-{!../../../docs_src/dependencies/tutorial012.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="16"
+ {!> ../../../docs_src/dependencies/tutorial012_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="16"
+ {!> ../../../docs_src/dependencies/tutorial012_an.py!}
+ ```
+
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="15"
+ {!> ../../../docs_src/dependencies/tutorial012.py!}
+ ```
And all the ideas in the section about [adding `dependencies` to the *path operation decorators*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} still apply, but in this case, to all of the *path operations* in the app.
diff --git a/docs/en/docs/tutorial/dependencies/index.md b/docs/en/docs/tutorial/dependencies/index.md
index 5078c0096..4f5ecea66 100644
--- a/docs/en/docs/tutorial/dependencies/index.md
+++ b/docs/en/docs/tutorial/dependencies/index.md
@@ -31,18 +31,42 @@ Let's first focus on the dependency.
It is just a function that can take all the same parameters that a *path operation function* can take:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="8-11"
- {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```Python hl_lines="8-9"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="8-11"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9-12"
+ {!> ../../../docs_src/dependencies/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="6-7"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="8-11"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
That's it.
**2 lines**.
@@ -61,42 +85,99 @@ In this case, this dependency expects:
And then it just returns a `dict` containing those values.
+!!! info
+ FastAPI added support for `Annotated` (and started recommending it) in version 0.95.0.
+
+ If you have an older version, you would get errors when trying to use `Annotated`.
+
+ Make sure you [Upgrade the FastAPI version](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} to at least 0.95.1 before using `Annotated`.
+
### Import `Depends`
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="3"
- {!> ../../../docs_src/dependencies/tutorial001.py!}
+ {!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/dependencies/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="1"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
### Declare the dependency, in the "dependant"
The same way you use `Body`, `Query`, etc. with your *path operation function* parameters, use `Depends` with a new parameter:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="15 20"
- {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```Python hl_lines="13 18"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="15 20"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="16 21"
+ {!> ../../../docs_src/dependencies/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="11 16"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="15 20"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
Although you use `Depends` in the parameters of your function the same way you use `Body`, `Query`, etc, `Depends` works a bit differently.
You only give `Depends` a single parameter.
This parameter must be something like a function.
+You **don't call it** directly (don't add the parenthesis at the end), you just pass it as a parameter to `Depends()`.
+
And that function takes parameters in the same way that *path operation functions* do.
!!! tip
@@ -126,6 +207,45 @@ This way you write shared code once and **FastAPI** takes care of calling it for
You just pass it to `Depends` and **FastAPI** knows how to do the rest.
+## Share `Annotated` dependencies
+
+In the examples above, you see that there's a tiny bit of **code duplication**.
+
+When you need to use the `common_parameters()` dependency, you have to write the whole parameter with the type annotation and `Depends()`:
+
+```Python
+commons: Annotated[dict, Depends(common_parameters)]
+```
+
+But because we are using `Annotated`, we can store that `Annotated` value in a variable and use it in multiple places:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="12 16 21"
+ {!> ../../../docs_src/dependencies/tutorial001_02_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="14 18 23"
+ {!> ../../../docs_src/dependencies/tutorial001_02_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="15 19 24"
+ {!> ../../../docs_src/dependencies/tutorial001_02_an.py!}
+ ```
+
+!!! tip
+ This is just standard Python, it's called a "type alias", it's actually not specific to **FastAPI**.
+
+ But because **FastAPI** is based on the Python standards, including `Annotated`, you can use this trick in your code. 😎
+
+The dependencies will keep working as expected, and the **best part** is that the **type information will be preserved**, which means that your editor will be able to keep providing you with **autocompletion**, **inline errors**, etc. The same for other tools like `mypy`.
+
+This will be especially useful when you use it in a **large code base** where you use **the same dependencies** over and over again in **many *path operations***.
+
## To `async` or not to `async`
As dependencies will also be called by **FastAPI** (the same as your *path operation functions*), the same rules apply while defining your functions.
diff --git a/docs/en/docs/tutorial/dependencies/sub-dependencies.md b/docs/en/docs/tutorial/dependencies/sub-dependencies.md
index a5b40c9ad..b50de1a46 100644
--- a/docs/en/docs/tutorial/dependencies/sub-dependencies.md
+++ b/docs/en/docs/tutorial/dependencies/sub-dependencies.md
@@ -10,18 +10,42 @@ They can be as **deep** as you need them to be.
You could create a first dependency ("dependable") like:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="8-9"
- {!> ../../../docs_src/dependencies/tutorial005.py!}
+ {!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="8-9"
+ {!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9-10"
+ {!> ../../../docs_src/dependencies/tutorial005_an.py!}
+ ```
+
+=== "Python 3.10 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="6-7"
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
```
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="8-9"
+ {!> ../../../docs_src/dependencies/tutorial005.py!}
+ ```
+
It declares an optional query parameter `q` as a `str`, and then it just returns it.
This is quite simple (not very useful), but will help us focus on how the sub-dependencies work.
@@ -30,18 +54,42 @@ This is quite simple (not very useful), but will help us focus on how the sub-de
Then you can create another dependency function (a "dependable") that at the same time declares a dependency of its own (so it is a "dependant" too):
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="13"
- {!> ../../../docs_src/dependencies/tutorial005.py!}
+ {!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/dependencies/tutorial005_an.py!}
+ ```
+
+=== "Python 3.10 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="11"
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
```
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/dependencies/tutorial005.py!}
+ ```
+
Let's focus on the parameters declared:
* Even though this function is a dependency ("dependable") itself, it also declares another dependency (it "depends" on something else).
@@ -53,18 +101,42 @@ Let's focus on the parameters declared:
Then we can use the dependency with:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="22"
- {!> ../../../docs_src/dependencies/tutorial005.py!}
+ ```Python hl_lines="23"
+ {!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="23"
+ {!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/dependencies/tutorial005_an.py!}
+ ```
+
+=== "Python 3.10 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
```
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/dependencies/tutorial005.py!}
+ ```
+
!!! info
Notice that we are only declaring one dependency in the *path operation function*, the `query_or_cookie_extractor`.
@@ -89,10 +161,22 @@ And it will save the returned value in a ../../../docs_src/encoder/tutorial001.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="4 21"
{!> ../../../docs_src/encoder/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="5 22"
+ {!> ../../../docs_src/encoder/tutorial001.py!}
+ ```
+
In this example, it would convert the Pydantic model to a `dict`, and the `datetime` to a `str`.
The result of calling it is something that can be encoded with the Python standard `json.dumps()`.
diff --git a/docs/en/docs/tutorial/extra-data-types.md b/docs/en/docs/tutorial/extra-data-types.md
index fb3efd318..7d6ffbc78 100644
--- a/docs/en/docs/tutorial/extra-data-types.md
+++ b/docs/en/docs/tutorial/extra-data-types.md
@@ -55,28 +55,76 @@ Here are some of the additional data types you can use:
Here's an example *path operation* with parameters using some of the above types.
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="1 3 12-16"
- {!> ../../../docs_src/extra_data_types/tutorial001.py!}
+ {!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="1 3 12-16"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 3 13-17"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="1 2 11-15"
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
```
-Note that the parameters inside the function have their natural data type, and you can, for example, perform normal date manipulations, like:
+=== "Python 3.6+ non-Annotated"
-=== "Python 3.6 and above"
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="18-19"
+ ```Python hl_lines="1 2 12-16"
{!> ../../../docs_src/extra_data_types/tutorial001.py!}
```
-=== "Python 3.10 and above"
+Note that the parameters inside the function have their natural data type, and you can, for example, perform normal date manipulations, like:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="18-19"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="18-19"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="19-20"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="17-18"
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="18-19"
+ {!> ../../../docs_src/extra_data_types/tutorial001.py!}
+ ```
diff --git a/docs/en/docs/tutorial/extra-models.md b/docs/en/docs/tutorial/extra-models.md
index 72fc74894..e91e879e4 100644
--- a/docs/en/docs/tutorial/extra-models.md
+++ b/docs/en/docs/tutorial/extra-models.md
@@ -17,18 +17,18 @@ This is especially the case for user models, because:
Here's a general idea of how the models could look like with their password fields and the places where they are used:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
- {!> ../../../docs_src/extra_models/tutorial001.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="7 9 14 20 22 27-28 31-33 38-39"
{!> ../../../docs_src/extra_models/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
+ {!> ../../../docs_src/extra_models/tutorial001.py!}
+ ```
+
### About `**user_in.dict()`
#### Pydantic's `.dict()`
@@ -158,18 +158,18 @@ All the data conversion, validation, documentation, etc. will still work as norm
That way, we can declare just the differences between the models (with plaintext `password`, with `hashed_password` and without password):
-=== "Python 3.6 and above"
-
- ```Python hl_lines="9 15-16 19-20 23-24"
- {!> ../../../docs_src/extra_models/tutorial002.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="7 13-14 17-18 21-22"
{!> ../../../docs_src/extra_models/tutorial002_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 15-16 19-20 23-24"
+ {!> ../../../docs_src/extra_models/tutorial002.py!}
+ ```
+
## `Union` or `anyOf`
You can declare a response to be the `Union` of two types, that means, that the response would be any of the two.
@@ -181,18 +181,18 @@ To do that, use the standard Python type hint `Union`, include the most specific type first, followed by the less specific type. In the example below, the more specific `PlaneItem` comes before `CarItem` in `Union[PlaneItem, CarItem]`.
-=== "Python 3.6 and above"
-
- ```Python hl_lines="1 14-15 18-20 33"
- {!> ../../../docs_src/extra_models/tutorial003.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="1 14-15 18-20 33"
{!> ../../../docs_src/extra_models/tutorial003_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 14-15 18-20 33"
+ {!> ../../../docs_src/extra_models/tutorial003.py!}
+ ```
+
### `Union` in Python 3.10
In this example we pass `Union[PlaneItem, CarItem]` as the value of the argument `response_model`.
@@ -213,18 +213,18 @@ The same way, you can declare responses of lists of objects.
For that, use the standard Python `typing.List` (or just `list` in Python 3.9 and above):
-=== "Python 3.6 and above"
-
- ```Python hl_lines="1 20"
- {!> ../../../docs_src/extra_models/tutorial004.py!}
- ```
-
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="18"
{!> ../../../docs_src/extra_models/tutorial004_py39.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 20"
+ {!> ../../../docs_src/extra_models/tutorial004.py!}
+ ```
+
## Response with arbitrary `dict`
You can also declare a response using a plain arbitrary `dict`, declaring just the type of the keys and values, without using a Pydantic model.
@@ -233,18 +233,18 @@ This is useful if you don't know the valid field/attribute names (that would be
In this case, you can use `typing.Dict` (or just `dict` in Python 3.9 and above):
-=== "Python 3.6 and above"
-
- ```Python hl_lines="1 8"
- {!> ../../../docs_src/extra_models/tutorial005.py!}
- ```
-
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="6"
{!> ../../../docs_src/extra_models/tutorial005_py39.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 8"
+ {!> ../../../docs_src/extra_models/tutorial005.py!}
+ ```
+
## Recap
Use multiple Pydantic models and inherit freely for each case.
diff --git a/docs/en/docs/tutorial/header-params.md b/docs/en/docs/tutorial/header-params.md
index 8e294416c..9e928cdc6 100644
--- a/docs/en/docs/tutorial/header-params.md
+++ b/docs/en/docs/tutorial/header-params.md
@@ -6,36 +6,84 @@ You can define Header parameters the same way you define `Query`, `Path` and `Co
First import `Header`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="3"
- {!> ../../../docs_src/header_params/tutorial001.py!}
+ {!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/header_params/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="1"
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/header_params/tutorial001.py!}
+ ```
+
## Declare `Header` parameters
Then declare the header parameters using the same structure as with `Path`, `Query` and `Cookie`.
The first value is the default value, you can pass all the extra validation or annotation parameters:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="9"
- {!> ../../../docs_src/header_params/tutorial001.py!}
+ {!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/header_params/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial001.py!}
+ ```
+
!!! note "Technical Details"
`Header` is a "sister" class of `Path`, `Query` and `Cookie`. It also inherits from the same common `Param` class.
@@ -60,18 +108,42 @@ So, you can use `user_agent` as you normally would in Python code, instead of ne
If for some reason you need to disable automatic conversion of underscores to hyphens, set the parameter `convert_underscores` of `Header` to `False`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="10"
- {!> ../../../docs_src/header_params/tutorial002.py!}
+ {!> ../../../docs_src/header_params/tutorial002_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/header_params/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/header_params/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="8"
{!> ../../../docs_src/header_params/tutorial002_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/header_params/tutorial002.py!}
+ ```
+
!!! warning
Before setting `convert_underscores` to `False`, bear in mind that some HTTP proxies and servers disallow the usage of headers with underscores.
@@ -85,22 +157,49 @@ You will receive all the values from the duplicate header as a Python `list`.
For example, to declare a header of `X-Token` that can appear more than once, you can write:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="9"
- {!> ../../../docs_src/header_params/tutorial003.py!}
+ {!> ../../../docs_src/header_params/tutorial003_an_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/header_params/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/header_params/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial003_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+ non-Annotated"
- ```Python hl_lines="7"
- {!> ../../../docs_src/header_params/tutorial003_py310.py!}
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial003.py!}
```
If you communicate with that *path operation* sending two HTTP headers like:
diff --git a/docs/en/docs/tutorial/path-operation-configuration.md b/docs/en/docs/tutorial/path-operation-configuration.md
index 884a762e2..7d4d4bcca 100644
--- a/docs/en/docs/tutorial/path-operation-configuration.md
+++ b/docs/en/docs/tutorial/path-operation-configuration.md
@@ -13,22 +13,22 @@ You can pass directly the `int` code, like `404`.
But if you don't remember what each number code is for, you can use the shortcut constants in `status`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="3 17"
- {!> ../../../docs_src/path_operation_configuration/tutorial001.py!}
+ ```Python hl_lines="1 15"
+ {!> ../../../docs_src/path_operation_configuration/tutorial001_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="3 17"
{!> ../../../docs_src/path_operation_configuration/tutorial001_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="1 15"
- {!> ../../../docs_src/path_operation_configuration/tutorial001_py310.py!}
+ ```Python hl_lines="3 17"
+ {!> ../../../docs_src/path_operation_configuration/tutorial001.py!}
```
That status code will be used in the response and will be added to the OpenAPI schema.
@@ -42,22 +42,22 @@ That status code will be used in the response and will be added to the OpenAPI s
You can add tags to your *path operation*, pass the parameter `tags` with a `list` of `str` (commonly just one `str`):
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="17 22 27"
- {!> ../../../docs_src/path_operation_configuration/tutorial002.py!}
+ ```Python hl_lines="15 20 25"
+ {!> ../../../docs_src/path_operation_configuration/tutorial002_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="17 22 27"
{!> ../../../docs_src/path_operation_configuration/tutorial002_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="15 20 25"
- {!> ../../../docs_src/path_operation_configuration/tutorial002_py310.py!}
+ ```Python hl_lines="17 22 27"
+ {!> ../../../docs_src/path_operation_configuration/tutorial002.py!}
```
They will be added to the OpenAPI schema and used by the automatic documentation interfaces:
@@ -80,22 +80,22 @@ In these cases, it could make sense to store the tags in an `Enum`.
You can add a `summary` and `description`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="20-21"
- {!> ../../../docs_src/path_operation_configuration/tutorial003.py!}
+ ```Python hl_lines="18-19"
+ {!> ../../../docs_src/path_operation_configuration/tutorial003_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="20-21"
{!> ../../../docs_src/path_operation_configuration/tutorial003_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="18-19"
- {!> ../../../docs_src/path_operation_configuration/tutorial003_py310.py!}
+ ```Python hl_lines="20-21"
+ {!> ../../../docs_src/path_operation_configuration/tutorial003.py!}
```
## Description from docstring
@@ -104,22 +104,22 @@ As descriptions tend to be long and cover multiple lines, you can declare the *p
You can write Markdown in the docstring, it will be interpreted and displayed correctly (taking into account docstring indentation).
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="19-27"
- {!> ../../../docs_src/path_operation_configuration/tutorial004.py!}
+ ```Python hl_lines="17-25"
+ {!> ../../../docs_src/path_operation_configuration/tutorial004_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="19-27"
{!> ../../../docs_src/path_operation_configuration/tutorial004_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="17-25"
- {!> ../../../docs_src/path_operation_configuration/tutorial004_py310.py!}
+ ```Python hl_lines="19-27"
+ {!> ../../../docs_src/path_operation_configuration/tutorial004.py!}
```
It will be used in the interactive docs:
@@ -130,22 +130,22 @@ It will be used in the interactive docs:
You can specify the response description with the parameter `response_description`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="21"
- {!> ../../../docs_src/path_operation_configuration/tutorial005.py!}
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/path_operation_configuration/tutorial005_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="21"
{!> ../../../docs_src/path_operation_configuration/tutorial005_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="19"
- {!> ../../../docs_src/path_operation_configuration/tutorial005_py310.py!}
+ ```Python hl_lines="21"
+ {!> ../../../docs_src/path_operation_configuration/tutorial005.py!}
```
!!! info
diff --git a/docs/en/docs/tutorial/path-params-numeric-validations.md b/docs/en/docs/tutorial/path-params-numeric-validations.md
index cec54b0fb..9255875d6 100644
--- a/docs/en/docs/tutorial/path-params-numeric-validations.md
+++ b/docs/en/docs/tutorial/path-params-numeric-validations.md
@@ -4,19 +4,50 @@ In the same way that you can declare more validations and metadata for query par
## Import Path
-First, import `Path` from `fastapi`:
+First, import `Path` from `fastapi`, and import `Annotated`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
+
+ ```Python hl_lines="1 3"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="1 3"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="3-4"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="3"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
```
-=== "Python 3.10 and above"
+!!! info
+ FastAPI added support for `Annotated` (and started recommending it) in version 0.95.0.
- ```Python hl_lines="1"
- {!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
- ```
+ If you have an older version, you would get errors when trying to use `Annotated`.
+
+ Make sure you [Upgrade the FastAPI version](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} to at least 0.95.1 before using `Annotated`.
## Declare metadata
@@ -24,18 +55,42 @@ You can declare all the same parameters as for `Query`.
For example, to declare a `title` metadata value for the path parameter `item_id` you can type:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="10"
- {!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="8"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
+ ```
+
!!! note
A path parameter is always required as it has to be part of the path.
@@ -45,11 +100,14 @@ For example, to declare a `title` metadata value for the path parameter `item_id
## Order the parameters as you need
+!!! tip
+ This is probably not as important or necessary if you use `Annotated`.
+
Let's say that you want to declare the query parameter `q` as a required `str`.
And you don't need to declare anything else for that parameter, so you don't really need to use `Query`.
-But you still need to use `Path` for the `item_id` path parameter.
+But you still need to use `Path` for the `item_id` path parameter. And you don't want to use `Annotated` for some reason.
Python will complain if you put a value with a "default" before a value that doesn't have a "default".
@@ -59,13 +117,44 @@ It doesn't matter for **FastAPI**. It will detect the parameters by their names,
So, you can declare your function as:
-```Python hl_lines="7"
-{!../../../docs_src/path_params_numeric_validations/tutorial002.py!}
-```
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial002.py!}
+ ```
+
+But have in mind that if you use `Annotated`, you won't have this problem, it won't matter as you're not using the function parameter default values for `Query()` or `Path()`.
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial002_an.py!}
+ ```
## Order the parameters as you need, tricks
-If you want to declare the `q` query parameter without a `Query` nor any default value, and the path parameter `item_id` using `Path`, and have them in a different order, Python has a little special syntax for that.
+!!! tip
+ This is probably not as important or necessary if you use `Annotated`.
+
+Here's a **small trick** that can be handy, but you won't need it often.
+
+If you want to:
+
+* declare the `q` query parameter without a `Query` nor any default value
+* declare the path parameter `item_id` using `Path`
+* have them in a different order
+* not use `Annotated`
+
+...Python has a little special syntax for that.
Pass `*`, as the first parameter of the function.
@@ -75,15 +164,48 @@ Python won't do anything with that `*`, but it will know that all the following
{!../../../docs_src/path_params_numeric_validations/tutorial003.py!}
```
+### Better with `Annotated`
+
+Have in mind that if you use `Annotated`, as you are not using function parameter default values, you won't have this problem, and you probably won't need to use `*`.
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial003_an.py!}
+ ```
+
## Number validations: greater than or equal
With `Query` and `Path` (and others you'll see later) you can declare number constraints.
Here, with `ge=1`, `item_id` will need to be an integer number "`g`reater than or `e`qual" to `1`.
-```Python hl_lines="8"
-{!../../../docs_src/path_params_numeric_validations/tutorial004.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial004_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial004.py!}
+ ```
## Number validations: greater than and less than or equal
@@ -92,9 +214,26 @@ The same applies for:
* `gt`: `g`reater `t`han
* `le`: `l`ess than or `e`qual
-```Python hl_lines="9"
-{!../../../docs_src/path_params_numeric_validations/tutorial005.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial005_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial005.py!}
+ ```
## Number validations: floats, greater than and less than
@@ -106,9 +245,26 @@ So, `0.5` would be a valid value. But `0.0` or `0` would not.
And the same for lt.
-```Python hl_lines="11"
-{!../../../docs_src/path_params_numeric_validations/tutorial006.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial006_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial006.py!}
+ ```
## Recap
diff --git a/docs/en/docs/tutorial/query-params-str-validations.md b/docs/en/docs/tutorial/query-params-str-validations.md
index 060e1d58a..c4b221cb1 100644
--- a/docs/en/docs/tutorial/query-params-str-validations.md
+++ b/docs/en/docs/tutorial/query-params-str-validations.md
@@ -4,18 +4,18 @@
Let's take this application as example:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="9"
- {!> ../../../docs_src/query_params_str_validations/tutorial001.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial001.py!}
+ ```
+
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
@@ -27,39 +27,124 @@ The query parameter `q` is of type `Union[str, None]` (or `str | None` in Python
We are going to enforce that even though `q` is optional, whenever it is provided, **its length doesn't exceed 50 characters**.
-### Import `Query`
+### Import `Query` and `Annotated`
-To achieve that, first import `Query` from `fastapi`:
+To achieve that, first import:
-=== "Python 3.6 and above"
+* `Query` from `fastapi`
+* `Annotated` from `typing` (or from `typing_extensions` in Python below 3.9)
- ```Python hl_lines="3"
- {!> ../../../docs_src/query_params_str_validations/tutorial002.py!}
+=== "Python 3.10+"
+
+ In Python 3.9 or above, `Annotated` is part of the standard library, so you can import it from `typing`.
+
+ ```Python hl_lines="1 3"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="1"
- {!> ../../../docs_src/query_params_str_validations/tutorial002_py310.py!}
+ In versions of Python below Python 3.9 you import `Annotation` from `typing_extensions`.
+
+ It will already be installed with FastAPI.
+
+ ```Python hl_lines="3-4"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002_an.py!}
```
-## Use `Query` as the default value
+!!! info
+ FastAPI added support for `Annotated` (and started recommending it) in version 0.95.0.
-And now use it as the default value of your parameter, setting the parameter `max_length` to 50:
+ If you have an older version, you would get errors when trying to use `Annotated`.
-=== "Python 3.6 and above"
+ Make sure you [Upgrade the FastAPI version](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} to at least 0.95.1 before using `Annotated`.
+
+## Use `Annotated` in the type for the `q` parameter
+
+Remember I told you before that `Annotated` can be used to add metadata to your parameters in the [Python Types Intro](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}?
+
+Now it's the time to use it with FastAPI. 🚀
+
+We had this type annotation:
+
+=== "Python 3.10+"
+
+ ```Python
+ q: str | None = None
+ ```
+
+=== "Python 3.6+"
+
+ ```Python
+ q: Union[str, None] = None
+ ```
+
+What we will do is wrap that with `Annotated`, so it becomes:
+
+=== "Python 3.10+"
+
+ ```Python
+ q: Annotated[str | None] = None
+ ```
+
+=== "Python 3.6+"
+
+ ```Python
+ q: Annotated[Union[str, None]] = None
+ ```
+
+Both of those versions mean the same thing, `q` is a parameter that can be a `str` or `None`, and by default, it is `None`.
+
+Now let's jump to the fun stuff. 🎉
+
+## Add `Query` to `Annotated` in the `q` parameter
+
+Now that we have this `Annotated` where we can put more metadata, add `Query` to it, and set the parameter `max_length` to 50:
+
+=== "Python 3.10+"
```Python hl_lines="9"
- {!> ../../../docs_src/query_params_str_validations/tutorial002.py!}
+ {!> ../../../docs_src/query_params_str_validations/tutorial002_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002_an.py!}
+ ```
+
+Notice that the default value is still `None`, so the parameter is still optional.
+
+But now, having `Query(max_length=50)` inside of `Annotated`, we are telling FastAPI that we want it to extract this value from the query parameters (this would have been the default anyway 🤷) and that we want to have **additional validation** for this value (that's why we do this, to get the additional validation). 😎
+
+FastAPI will now:
+
+* **Validate** the data making sure that the max length is 50 characters
+* Show a **clear error** for the client when the data is not valid
+* **Document** the parameter in the OpenAPI schema *path operation* (so it will show up in the **automatic docs UI**)
+
+## Alternative (old) `Query` as the default value
+
+Previous versions of FastAPI (before 0.95.0) required you to use `Query` as the default value of your parameter, instead of putting it in `Annotated`, there's a high chance that you will see code using it around, so I'll explain it to you.
+
+!!! tip
+ For new code and whenever possible, use `Annotated` as explained above. There are multiple advantages (explained below) and no disadvantages. 🍰
+
+This is how you would use `Query()` as the default value of your function parameter, setting the parameter `max_length` to 50:
+
+=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial002_py310.py!}
```
-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.
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002.py!}
+ ```
+
+As in this case (without using `Annotated`) we have to replace the default value `None` in the function with `Query()`, we now need to set the default value with the parameter `Query(default=None)`, it serves the same purpose of defining that default value (at least for FastAPI).
So:
@@ -67,7 +152,7 @@ So:
q: Union[str, None] = Query(default=None)
```
-...makes the parameter optional, the same as:
+...makes the parameter optional, with a default value of `None`, the same as:
```Python
q: Union[str, None] = None
@@ -79,7 +164,7 @@ And in Python 3.10 and above:
q: str | None = Query(default=None)
```
-...makes the parameter optional, the same as:
+...makes the parameter optional, with a default value of `None`, the same as:
```Python
q: str | None = None
@@ -112,38 +197,124 @@ 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*.
+### `Query` as the default value or in `Annotated`
+
+Have in mind that when using `Query` inside of `Annotated` you cannot use the `default` parameter for `Query`.
+
+Instead use the actual default value of the function parameter. Otherwise, it would be inconsistent.
+
+For example, this is not allowed:
+
+```Python
+q: Annotated[str, Query(default="rick")] = "morty"
+```
+
+...because it's not clear if the default value should be `"rick"` or `"morty"`.
+
+So, you would use (preferably):
+
+```Python
+q: Annotated[str, Query()] = "rick"
+```
+
+...or in older code bases you will find:
+
+```Python
+q: str = Query(default="rick")
+```
+
+### Advantages of `Annotated`
+
+**Using `Annotated` is recommended** instead of the default value in function parameters, it is **better** for multiple reasons. 🤓
+
+The **default** value of the **function parameter** is the **actual default** value, that's more intuitive with Python in general. 😌
+
+You could **call** that same function in **other places** without FastAPI, and it would **work as expected**. If there's a **required** parameter (without a default value), your **editor** will let you know with an error, **Python** will also complain if you run it without passing the required parameter.
+
+When you don't use `Annotated` and instead use the **(old) default value style**, if you call that function without FastAPI in **other place**, you have to **remember** to pass the arguments to the function for it to work correctly, otherwise the values will be different from what you expect (e.g. `QueryInfo` or something similar instead of `str`). And your editor won't complain, and Python won't complain running that function, only when the operations inside error out.
+
+Because `Annotated` can have more than one metadata annotation, you could now even use the same function with other tools, like Typer. 🚀
+
## Add more validations
You can also add a parameter `min_length`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="10"
- {!> ../../../docs_src/query_params_str_validations/tutorial003.py!}
+ {!> ../../../docs_src/query_params_str_validations/tutorial003_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial003_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial003.py!}
+ ```
+
## Add regular expressions
You can define a regular expression that the parameter should match:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="11"
- {!> ../../../docs_src/query_params_str_validations/tutorial004.py!}
+ {!> ../../../docs_src/query_params_str_validations/tutorial004_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial004_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/query_params_str_validations/tutorial004_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial004_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial004.py!}
+ ```
+
This specific regular expression checks that the received parameter value:
* `^`: starts with the following characters, doesn't have characters before.
@@ -156,16 +327,33 @@ 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 value for the `default` parameter, you can pass other values.
+You can, of course, use default values other than `None`.
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"`:
-```Python hl_lines="7"
-{!../../../docs_src/query_params_str_validations/tutorial005.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial005_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial005.py!}
+ ```
!!! note
- Having a default value also makes the parameter optional.
+ Having a default value of any type, including `None`, makes the parameter optional (not required).
## Make it required
@@ -183,23 +371,70 @@ q: Union[str, None] = None
But we are now declaring it with `Query`, for example like:
-```Python
-q: Union[str, None] = Query(default=None, min_length=3)
-```
+=== "Annotated"
+
+ ```Python
+ q: Annotated[Union[str, None], Query(min_length=3)] = None
+ ```
+
+=== "non-Annotated"
+
+ ```Python
+ 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 simply not declare a default value:
-```Python hl_lines="7"
-{!../../../docs_src/query_params_str_validations/tutorial006.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006.py!}
+ ```
+
+ !!! tip
+ Notice that, even though in this case the `Query()` is used as the function parameter default value, we don't pass the `default=None` to `Query()`.
+
+ Still, probably better to use the `Annotated` version. 😉
### 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 `...`:
+There's an alternative way to explicitly declare that a value is required. You can set the default to the literal value `...`:
-```Python hl_lines="7"
-{!../../../docs_src/query_params_str_validations/tutorial006b.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006b_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006b_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```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 part of Python and is called "Ellipsis".
@@ -212,20 +447,44 @@ This will let **FastAPI** know that this parameter is required.
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=...`:
+To do that, you can declare that `None` is a valid type but still use `...` as the default:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="9"
- {!> ../../../docs_src/query_params_str_validations/tutorial006c.py!}
+ {!> ../../../docs_src/query_params_str_validations/tutorial006c_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006c_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006c_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial006c_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006c.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 Required Optional fields.
@@ -233,12 +492,29 @@ To do that, you can declare that `None` is a valid type but still use `default=.
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!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="4 10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006d_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="2 9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006d_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```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`.
+ Remember that in most of the cases, when something is required, you can simply omit the default, so you normally don't have to use `...` nor `Required`.
## Query parameter list / multiple values
@@ -246,22 +522,49 @@ When you define a query parameter explicitly with `Query` you can also declare i
For example, to declare a query parameter `q` that can appear multiple times in the URL, you can write:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="9"
- {!> ../../../docs_src/query_params_str_validations/tutorial011.py!}
+ {!> ../../../docs_src/query_params_str_validations/tutorial011_an_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011_py310.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial011_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+ non-Annotated"
- ```Python hl_lines="7"
- {!> ../../../docs_src/query_params_str_validations/tutorial011_py310.py!}
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011.py!}
```
Then, with a URL like:
@@ -294,18 +597,36 @@ The interactive API docs will update accordingly, to allow multiple values:
And you can also define a default `list` of values if none are provided:
-=== "Python 3.6 and above"
+=== "Python 3.9+"
```Python hl_lines="9"
- {!> ../../../docs_src/query_params_str_validations/tutorial012.py!}
+ {!> ../../../docs_src/query_params_str_validations/tutorial012_an_py39.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial012_an.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial012_py39.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial012.py!}
+ ```
+
If you go to:
```
@@ -327,9 +648,26 @@ the default of `q` will be: `["foo", "bar"]` and your response will be:
You can also use `list` directly instead of `List[str]` (or `list[str]` in Python 3.9+):
-```Python hl_lines="7"
-{!../../../docs_src/query_params_str_validations/tutorial013.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial013_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial013_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial013.py!}
+ ```
!!! note
Have in mind that in this case, FastAPI won't check the contents of the list.
@@ -349,32 +687,80 @@ That information will be included in the generated OpenAPI and used by the docum
You can add a `title`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="10"
- {!> ../../../docs_src/query_params_str_validations/tutorial007.py!}
+ {!> ../../../docs_src/query_params_str_validations/tutorial007_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial007_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial007_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="8"
{!> ../../../docs_src/query_params_str_validations/tutorial007_py310.py!}
```
-And a `description`:
+=== "Python 3.6+ non-Annotated"
-=== "Python 3.6 and above"
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="13"
- {!> ../../../docs_src/query_params_str_validations/tutorial008.py!}
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial007.py!}
```
-=== "Python 3.10 and above"
+And a `description`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/query_params_str_validations/tutorial008_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/query_params_str_validations/tutorial008_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="15"
+ {!> ../../../docs_src/query_params_str_validations/tutorial008_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="12"
{!> ../../../docs_src/query_params_str_validations/tutorial008_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/query_params_str_validations/tutorial008.py!}
+ ```
+
## Alias parameters
Imagine that you want the parameter to be `item-query`.
@@ -393,18 +779,42 @@ But you still need it to be exactly `item-query`...
Then you can declare an `alias`, and that alias is what will be used to find the parameter value:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="9"
- {!> ../../../docs_src/query_params_str_validations/tutorial009.py!}
+ {!> ../../../docs_src/query_params_str_validations/tutorial009_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial009_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial009_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial009_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial009.py!}
+ ```
+
## Deprecating parameters
Now let's say you don't like this parameter anymore.
@@ -413,18 +823,42 @@ You have to leave it there a while because there are clients using it, but you w
Then pass the parameter `deprecated=True` to `Query`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="18"
- {!> ../../../docs_src/query_params_str_validations/tutorial010.py!}
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/query_params_str_validations/tutorial010_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/query_params_str_validations/tutorial010_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/query_params_str_validations/tutorial010_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="17"
{!> ../../../docs_src/query_params_str_validations/tutorial010_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/query_params_str_validations/tutorial010.py!}
+ ```
+
The docs will show it like this:
@@ -433,18 +867,42 @@ The docs will show it like this:
To exclude a query parameter from the generated OpenAPI schema (and thus, from the automatic documentation systems), set the parameter `include_in_schema` of `Query` to `False`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="10"
- {!> ../../../docs_src/query_params_str_validations/tutorial014.py!}
+ {!> ../../../docs_src/query_params_str_validations/tutorial014_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial014_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial014_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="8"
{!> ../../../docs_src/query_params_str_validations/tutorial014_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial014.py!}
+ ```
+
## Recap
You can declare additional validations and metadata for your parameters.
diff --git a/docs/en/docs/tutorial/query-params.md b/docs/en/docs/tutorial/query-params.md
index eec55502a..0b74b10f8 100644
--- a/docs/en/docs/tutorial/query-params.md
+++ b/docs/en/docs/tutorial/query-params.md
@@ -63,18 +63,18 @@ The parameter values in your function will be:
The same way, you can declare optional query parameters, by setting their default to `None`:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="9"
- {!> ../../../docs_src/query_params/tutorial002.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/query_params/tutorial002_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params/tutorial002.py!}
+ ```
+
In this case, the function parameter `q` will be optional, and will be `None` by default.
!!! check
@@ -84,18 +84,18 @@ In this case, the function parameter `q` will be optional, and will be `None` by
You can also declare `bool` types, and they will be converted:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="9"
- {!> ../../../docs_src/query_params/tutorial003.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/query_params/tutorial003_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params/tutorial003.py!}
+ ```
+
In this case, if you go to:
```
@@ -137,18 +137,18 @@ And you don't have to declare them in any specific order.
They will be detected by name:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="8 10"
- {!> ../../../docs_src/query_params/tutorial004.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="6 8"
{!> ../../../docs_src/query_params/tutorial004_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="8 10"
+ {!> ../../../docs_src/query_params/tutorial004.py!}
+ ```
+
## Required query parameters
When you declare a default value for non-path parameters (for now, we have only seen query parameters), then it is not required.
@@ -203,18 +203,18 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
And of course, you can define some parameters as required, some as having a default value, and some entirely optional:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="10"
- {!> ../../../docs_src/query_params/tutorial006.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="8"
{!> ../../../docs_src/query_params/tutorial006_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params/tutorial006.py!}
+ ```
+
In this case, there are 3 query parameters:
* `needy`, a required `str`.
diff --git a/docs/en/docs/tutorial/request-files.md b/docs/en/docs/tutorial/request-files.md
index 783783c58..1fe1e7a33 100644
--- a/docs/en/docs/tutorial/request-files.md
+++ b/docs/en/docs/tutorial/request-files.md
@@ -13,17 +13,51 @@ You can define files to be uploaded by the client using `File`.
Import `File` and `UploadFile` from `fastapi`:
-```Python hl_lines="1"
-{!../../../docs_src/request_files/tutorial001.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/request_files/tutorial001_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/request_files/tutorial001.py!}
+ ```
## Define `File` Parameters
Create file parameters the same way you would for `Body` or `Form`:
-```Python hl_lines="7"
-{!../../../docs_src/request_files/tutorial001.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/request_files/tutorial001_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/request_files/tutorial001.py!}
+ ```
!!! info
`File` is a class that inherits directly from `Form`.
@@ -45,9 +79,26 @@ But there are several cases in which you might benefit from using `UploadFile`.
Define a file parameter with a type of `UploadFile`:
-```Python hl_lines="12"
-{!../../../docs_src/request_files/tutorial001.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/request_files/tutorial001_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/request_files/tutorial001.py!}
+ ```
Using `UploadFile` has several advantages over `bytes`:
@@ -118,25 +169,66 @@ The way HTML forms (``) sends the data to the server normally uses
You can make a file optional by using standard type annotations and setting a default value of `None`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
+
+ ```Python hl_lines="9 17"
+ {!> ../../../docs_src/request_files/tutorial001_02_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9 17"
+ {!> ../../../docs_src/request_files/tutorial001_02_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10 18"
+ {!> ../../../docs_src/request_files/tutorial001_02_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7 15"
+ {!> ../../../docs_src/request_files/tutorial001_02_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="9 17"
{!> ../../../docs_src/request_files/tutorial001_02.py!}
```
-=== "Python 3.10 and above"
-
- ```Python hl_lines="7 14"
- {!> ../../../docs_src/request_files/tutorial001_02_py310.py!}
- ```
-
## `UploadFile` with Additional Metadata
You can also use `File()` with `UploadFile`, for example, to set additional metadata:
-```Python hl_lines="13"
-{!../../../docs_src/request_files/tutorial001_03.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="9 15"
+ {!> ../../../docs_src/request_files/tutorial001_03_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8 14"
+ {!> ../../../docs_src/request_files/tutorial001_03_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7 13"
+ {!> ../../../docs_src/request_files/tutorial001_03.py!}
+ ```
## Multiple File Uploads
@@ -146,18 +238,36 @@ They would be associated to the same "form field" sent using "form data".
To use that, declare a list of `bytes` or `UploadFile`:
-=== "Python 3.6 and above"
+=== "Python 3.9+"
```Python hl_lines="10 15"
- {!> ../../../docs_src/request_files/tutorial002.py!}
+ {!> ../../../docs_src/request_files/tutorial002_an_py39.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.6+"
+
+ ```Python hl_lines="11 16"
+ {!> ../../../docs_src/request_files/tutorial002_an.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="8 13"
{!> ../../../docs_src/request_files/tutorial002_py39.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="10 15"
+ {!> ../../../docs_src/request_files/tutorial002.py!}
+ ```
+
You will receive, as declared, a `list` of `bytes` or `UploadFile`s.
!!! note "Technical Details"
@@ -169,18 +279,36 @@ You will receive, as declared, a `list` of `bytes` or `UploadFile`s.
And the same way as before, you can use `File()` to set additional parameters, even for `UploadFile`:
-=== "Python 3.6 and above"
+=== "Python 3.9+"
- ```Python hl_lines="18"
- {!> ../../../docs_src/request_files/tutorial003.py!}
+ ```Python hl_lines="11 18-20"
+ {!> ../../../docs_src/request_files/tutorial003_an_py39.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.6+"
- ```Python hl_lines="16"
+ ```Python hl_lines="12 19-21"
+ {!> ../../../docs_src/request_files/tutorial003_an.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9 16"
{!> ../../../docs_src/request_files/tutorial003_py39.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="11 18"
+ {!> ../../../docs_src/request_files/tutorial003.py!}
+ ```
+
## Recap
Use `File`, `bytes`, and `UploadFile` to declare files to be uploaded in the request, sent as form data.
diff --git a/docs/en/docs/tutorial/request-forms-and-files.md b/docs/en/docs/tutorial/request-forms-and-files.md
index 6844f8c65..1818946c4 100644
--- a/docs/en/docs/tutorial/request-forms-and-files.md
+++ b/docs/en/docs/tutorial/request-forms-and-files.md
@@ -9,17 +9,51 @@ You can define files and form fields at the same time using `File` and `Form`.
## Import `File` and `Form`
-```Python hl_lines="1"
-{!../../../docs_src/request_forms_and_files/tutorial001.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
+ ```
## Define `File` and `Form` parameters
Create file and form parameters the same way you would for `Body` or `Query`:
-```Python hl_lines="8"
-{!../../../docs_src/request_forms_and_files/tutorial001.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="10-12"
+ {!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9-11"
+ {!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
+ ```
The files and form fields will be uploaded as form data and you will receive the files and form fields.
diff --git a/docs/en/docs/tutorial/request-forms.md b/docs/en/docs/tutorial/request-forms.md
index 26922685a..5d441a614 100644
--- a/docs/en/docs/tutorial/request-forms.md
+++ b/docs/en/docs/tutorial/request-forms.md
@@ -11,17 +11,51 @@ When you need to receive form fields instead of JSON, you can use `Form`.
Import `Form` from `fastapi`:
-```Python hl_lines="1"
-{!../../../docs_src/request_forms/tutorial001.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/request_forms/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/request_forms/tutorial001_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/request_forms/tutorial001.py!}
+ ```
## Define `Form` parameters
Create form parameters the same way you would for `Body` or `Query`:
-```Python hl_lines="7"
-{!../../../docs_src/request_forms/tutorial001.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/request_forms/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/request_forms/tutorial001_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/request_forms/tutorial001.py!}
+ ```
For example, in one of the ways the OAuth2 specification can be used (called "password flow") it is required to send a `username` and `password` as form fields.
diff --git a/docs/en/docs/tutorial/response-model.md b/docs/en/docs/tutorial/response-model.md
index cd7a749d4..2181cfb5a 100644
--- a/docs/en/docs/tutorial/response-model.md
+++ b/docs/en/docs/tutorial/response-model.md
@@ -4,22 +4,22 @@ You can declare the type used for the response by annotating the *path operation
You can use **type annotations** the same way you would for input data in function **parameters**, you can use Pydantic models, lists, dictionaries, scalar values like integers, booleans, etc.
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="18 23"
- {!> ../../../docs_src/response_model/tutorial001_01.py!}
+ ```Python hl_lines="16 21"
+ {!> ../../../docs_src/response_model/tutorial001_01_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="18 23"
{!> ../../../docs_src/response_model/tutorial001_01_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="16 21"
- {!> ../../../docs_src/response_model/tutorial001_01_py310.py!}
+ ```Python hl_lines="18 23"
+ {!> ../../../docs_src/response_model/tutorial001_01.py!}
```
FastAPI will use this return type to:
@@ -53,22 +53,22 @@ You can use the `response_model` parameter in any of the *path operations*:
* `@app.delete()`
* etc.
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="17 22 24-27"
- {!> ../../../docs_src/response_model/tutorial001.py!}
+ {!> ../../../docs_src/response_model/tutorial001_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="17 22 24-27"
{!> ../../../docs_src/response_model/tutorial001_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
```Python hl_lines="17 22 24-27"
- {!> ../../../docs_src/response_model/tutorial001_py310.py!}
+ {!> ../../../docs_src/response_model/tutorial001.py!}
```
!!! note
@@ -95,18 +95,18 @@ You can also use `response_model=None` to disable creating a response model for
Here we are declaring a `UserIn` model, it will contain a plaintext password:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="9 11"
- {!> ../../../docs_src/response_model/tutorial002.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="7 9"
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 11"
+ {!> ../../../docs_src/response_model/tutorial002.py!}
+ ```
+
!!! info
To use `EmailStr`, first install `email_validator`.
@@ -115,18 +115,18 @@ Here we are declaring a `UserIn` model, it will contain a plaintext password:
And we are using this model to declare our input and the same model to declare our output:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="18"
- {!> ../../../docs_src/response_model/tutorial002.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="16"
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/response_model/tutorial002.py!}
+ ```
+
Now, whenever a browser is creating a user with a password, the API will return the same password in the response.
In this case, it might not be a problem, because it's the same user sending the password.
@@ -140,46 +140,46 @@ But if we use the same model for another *path operation*, we could be sending o
We can instead create an input model with the plaintext password and an output model without it:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="9 11 16"
- {!> ../../../docs_src/response_model/tutorial003.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="9 11 16"
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 11 16"
+ {!> ../../../docs_src/response_model/tutorial003.py!}
+ ```
+
Here, even though our *path operation function* is returning the same input user that contains the password:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="24"
- {!> ../../../docs_src/response_model/tutorial003.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/response_model/tutorial003.py!}
+ ```
+
...we declared the `response_model` to be our model `UserOut`, that doesn't include the password:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="22"
- {!> ../../../docs_src/response_model/tutorial003.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="22"
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/response_model/tutorial003.py!}
+ ```
+
So, **FastAPI** will take care of filtering out all the data that is not declared in the output model (using Pydantic).
### `response_model` or Return Type
@@ -202,18 +202,18 @@ But in most of the cases where we need to do something like this, we want the mo
And in those cases, we can use classes and inheritance to take advantage of function **type annotations** to get better support in the editor and tools, and still get the FastAPI **data filtering**.
-=== "Python 3.6 and above"
-
- ```Python hl_lines="9-13 15-16 20"
- {!> ../../../docs_src/response_model/tutorial003_01.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="7-10 13-14 18"
{!> ../../../docs_src/response_model/tutorial003_01_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9-13 15-16 20"
+ {!> ../../../docs_src/response_model/tutorial003_01.py!}
+ ```
+
With this, we get tooling support, from editors and mypy as this code is correct in terms of types, but we also get the data filtering from FastAPI.
How does this work? Let's check that out. 🤓
@@ -278,18 +278,18 @@ But when you return some other arbitrary object that is not a valid Pydantic typ
The same would happen if you had something like a union between different types where one or more of them are not valid Pydantic types, for example this would fail 💥:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="10"
- {!> ../../../docs_src/response_model/tutorial003_04.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="8"
{!> ../../../docs_src/response_model/tutorial003_04_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/response_model/tutorial003_04.py!}
+ ```
+
...this fails because the type annotation is not a Pydantic type and is not just a single `Response` class or subclass, it's a union (any of the two) between a `Response` and a `dict`.
### Disable Response Model
@@ -300,40 +300,40 @@ But you might want to still keep the return type annotation in the function to g
In this case, you can disable the response model generation by setting `response_model=None`:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="9"
- {!> ../../../docs_src/response_model/tutorial003_05.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/response_model/tutorial003_05_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/response_model/tutorial003_05.py!}
+ ```
+
This will make FastAPI skip the response model generation and that way you can have any return type annotations you need without it affecting your FastAPI application. 🤓
## Response Model encoding parameters
Your response model could have default values, like:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="11 13-14"
- {!> ../../../docs_src/response_model/tutorial004.py!}
+ ```Python hl_lines="9 11-12"
+ {!> ../../../docs_src/response_model/tutorial004_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="11 13-14"
{!> ../../../docs_src/response_model/tutorial004_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="9 11-12"
- {!> ../../../docs_src/response_model/tutorial004_py310.py!}
+ ```Python hl_lines="11 13-14"
+ {!> ../../../docs_src/response_model/tutorial004.py!}
```
* `description: Union[str, None] = None` (or `str | None = None` in Python 3.10) has a default of `None`.
@@ -348,22 +348,22 @@ For example, if you have models with many optional attributes in a NoSQL databas
You can set the *path operation decorator* parameter `response_model_exclude_unset=True`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="24"
- {!> ../../../docs_src/response_model/tutorial004.py!}
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/response_model/tutorial004_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial004_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="22"
- {!> ../../../docs_src/response_model/tutorial004_py310.py!}
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/response_model/tutorial004.py!}
```
and those default values won't be included in the response, only the values actually set.
@@ -441,18 +441,18 @@ This can be used as a quick shortcut if you have only one Pydantic model and wan
This also applies to `response_model_by_alias` that works similarly.
-=== "Python 3.6 and above"
-
- ```Python hl_lines="31 37"
- {!> ../../../docs_src/response_model/tutorial005.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="29 35"
{!> ../../../docs_src/response_model/tutorial005_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="31 37"
+ {!> ../../../docs_src/response_model/tutorial005.py!}
+ ```
+
!!! tip
The syntax `{"name", "description"}` creates a `set` with those two values.
@@ -462,18 +462,18 @@ This can be used as a quick shortcut if you have only one Pydantic model and wan
If you forget to use a `set` and use a `list` or `tuple` instead, FastAPI will still convert it to a `set` and it will work correctly:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="31 37"
- {!> ../../../docs_src/response_model/tutorial006.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="29 35"
{!> ../../../docs_src/response_model/tutorial006_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="31 37"
+ {!> ../../../docs_src/response_model/tutorial006.py!}
+ ```
+
## Recap
Use the *path operation decorator's* parameter `response_model` to define response models and especially to ensure private data is filtered out.
diff --git a/docs/en/docs/tutorial/schema-extra-example.md b/docs/en/docs/tutorial/schema-extra-example.md
index 94347018d..5312254d9 100644
--- a/docs/en/docs/tutorial/schema-extra-example.md
+++ b/docs/en/docs/tutorial/schema-extra-example.md
@@ -8,18 +8,18 @@ Here are several ways to do it.
You can declare an `example` for a Pydantic model using `Config` and `schema_extra`, as described in Pydantic's docs: Schema customization:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="15-23"
- {!> ../../../docs_src/schema_extra_example/tutorial001.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="13-21"
{!> ../../../docs_src/schema_extra_example/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="15-23"
+ {!> ../../../docs_src/schema_extra_example/tutorial001.py!}
+ ```
+
That extra info will be added as-is to the output **JSON Schema** for that model, and it will be used in the API docs.
!!! tip
@@ -33,18 +33,18 @@ When using `Field()` with Pydantic models, you can also declare extra info for t
You can use this to add `example` for each field:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="4 10-13"
- {!> ../../../docs_src/schema_extra_example/tutorial002.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="2 8-11"
{!> ../../../docs_src/schema_extra_example/tutorial002_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="4 10-13"
+ {!> ../../../docs_src/schema_extra_example/tutorial002.py!}
+ ```
+
!!! warning
Keep in mind that those extra arguments passed won't add any validation, only extra information, for documentation purposes.
@@ -66,18 +66,39 @@ you can also declare a data `example` or a group of `examples` with additional i
Here we pass an `example` of the data expected in `Body()`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="20-25"
- {!> ../../../docs_src/schema_extra_example/tutorial003.py!}
+ ```Python hl_lines="22-27"
+ {!> ../../../docs_src/schema_extra_example/tutorial003_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="22-27"
+ {!> ../../../docs_src/schema_extra_example/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="23-28"
+ {!> ../../../docs_src/schema_extra_example/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
```Python hl_lines="18-23"
{!> ../../../docs_src/schema_extra_example/tutorial003_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="20-25"
+ {!> ../../../docs_src/schema_extra_example/tutorial003.py!}
+ ```
+
### Example in the docs UI
With any of the methods above it would look like this in the `/docs`:
@@ -97,18 +118,39 @@ Each specific example `dict` in the `examples` can contain:
* `value`: This is the actual example shown, e.g. a `dict`.
* `externalValue`: alternative to `value`, a URL pointing to the example. Although this might not be supported by as many tools as `value`.
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="21-47"
- {!> ../../../docs_src/schema_extra_example/tutorial004.py!}
+ ```Python hl_lines="23-49"
+ {!> ../../../docs_src/schema_extra_example/tutorial004_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="23-49"
+ {!> ../../../docs_src/schema_extra_example/tutorial004_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="24-50"
+ {!> ../../../docs_src/schema_extra_example/tutorial004_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
```Python hl_lines="19-45"
{!> ../../../docs_src/schema_extra_example/tutorial004_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="21-47"
+ {!> ../../../docs_src/schema_extra_example/tutorial004.py!}
+ ```
+
### Examples in the docs UI
With `examples` added to `Body()` the `/docs` would look like:
diff --git a/docs/en/docs/tutorial/security/first-steps.md b/docs/en/docs/tutorial/security/first-steps.md
index 45ffaab90..5765cf2d6 100644
--- a/docs/en/docs/tutorial/security/first-steps.md
+++ b/docs/en/docs/tutorial/security/first-steps.md
@@ -20,9 +20,27 @@ Let's first just use the code and see how it works, and then we'll come back to
Copy the example in a file `main.py`:
-```Python
-{!../../../docs_src/security/tutorial001.py!}
-```
+=== "Python 3.9+"
+
+ ```Python
+ {!> ../../../docs_src/security/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python
+ {!> ../../../docs_src/security/tutorial001_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python
+ {!> ../../../docs_src/security/tutorial001.py!}
+ ```
+
## Run it
@@ -116,9 +134,26 @@ In this example we are going to use **OAuth2**, with the **Password** flow, usin
When we create an instance of the `OAuth2PasswordBearer` class we pass in the `tokenUrl` parameter. This parameter contains the URL that the client (the frontend running in the user's browser) will use to send the `username` and `password` in order to get a token.
-```Python hl_lines="6"
-{!../../../docs_src/security/tutorial001.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/security/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/security/tutorial001_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="6"
+ {!> ../../../docs_src/security/tutorial001.py!}
+ ```
!!! 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`.
@@ -150,9 +185,26 @@ So, it can be used with `Depends`.
Now you can pass that `oauth2_scheme` in a dependency with `Depends`.
-```Python hl_lines="10"
-{!../../../docs_src/security/tutorial001.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/security/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/security/tutorial001_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/security/tutorial001.py!}
+ ```
This dependency will provide a `str` that is assigned to the parameter `token` of the *path operation function*.
diff --git a/docs/en/docs/tutorial/security/get-current-user.md b/docs/en/docs/tutorial/security/get-current-user.md
index 13e867216..1a8c5d9a8 100644
--- a/docs/en/docs/tutorial/security/get-current-user.md
+++ b/docs/en/docs/tutorial/security/get-current-user.md
@@ -2,9 +2,26 @@
In the previous chapter the security system (which is based on the dependency injection system) was giving the *path operation function* a `token` as a `str`:
-```Python hl_lines="10"
-{!../../../docs_src/security/tutorial001.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/security/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/security/tutorial001_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/security/tutorial001.py!}
+ ```
But that is still not that useful.
@@ -16,18 +33,42 @@ First, let's create a Pydantic user model.
The same way we use Pydantic to declare bodies, we can use it anywhere else:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="5 12-16"
- {!> ../../../docs_src/security/tutorial002.py!}
+ {!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="5 12-16"
+ {!> ../../../docs_src/security/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="5 13-17"
+ {!> ../../../docs_src/security/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="3 10-14"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="5 12-16"
+ {!> ../../../docs_src/security/tutorial002.py!}
+ ```
+
## Create a `get_current_user` dependency
Let's create a dependency `get_current_user`.
@@ -38,50 +79,122 @@ Remember that dependencies can have sub-dependencies?
The same as we were doing before in the *path operation* directly, our new dependency `get_current_user` will receive a `token` as a `str` from the sub-dependency `oauth2_scheme`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="25"
- {!> ../../../docs_src/security/tutorial002.py!}
+ {!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="25"
+ {!> ../../../docs_src/security/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="26"
+ {!> ../../../docs_src/security/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="23"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="25"
+ {!> ../../../docs_src/security/tutorial002.py!}
+ ```
+
## Get the user
`get_current_user` will use a (fake) utility function we created, that takes a token as a `str` and returns our Pydantic `User` model:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="19-22 26-27"
- {!> ../../../docs_src/security/tutorial002.py!}
+ {!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="19-22 26-27"
+ {!> ../../../docs_src/security/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="20-23 27-28"
+ {!> ../../../docs_src/security/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="17-20 24-25"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="19-22 26-27"
+ {!> ../../../docs_src/security/tutorial002.py!}
+ ```
+
## Inject the current user
So now we can use the same `Depends` with our `get_current_user` in the *path operation*:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="31"
- {!> ../../../docs_src/security/tutorial002.py!}
+ {!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="31"
+ {!> ../../../docs_src/security/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="32"
+ {!> ../../../docs_src/security/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="29"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="31"
+ {!> ../../../docs_src/security/tutorial002.py!}
+ ```
+
Notice that we declare the type of `current_user` as the Pydantic model `User`.
This will help us inside of the function with all the completion and type checks.
@@ -128,18 +241,42 @@ And all of them (or any portion of them that you want) can take the advantage of
And all these thousands of *path operations* can be as small as 3 lines:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="30-32"
- {!> ../../../docs_src/security/tutorial002.py!}
+ {!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="30-32"
+ {!> ../../../docs_src/security/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="31-33"
+ {!> ../../../docs_src/security/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="28-30"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="30-32"
+ {!> ../../../docs_src/security/tutorial002.py!}
+ ```
+
## Recap
You can now get the current user directly in your *path operation function*.
diff --git a/docs/en/docs/tutorial/security/oauth2-jwt.md b/docs/en/docs/tutorial/security/oauth2-jwt.md
index 41f00fd41..deb722b96 100644
--- a/docs/en/docs/tutorial/security/oauth2-jwt.md
+++ b/docs/en/docs/tutorial/security/oauth2-jwt.md
@@ -109,18 +109,42 @@ And another utility to verify if a received password matches the hash stored.
And another one to authenticate and return a user.
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="7 48 55-56 59-60 69-75"
- {!> ../../../docs_src/security/tutorial004.py!}
+ {!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="7 48 55-56 59-60 69-75"
+ {!> ../../../docs_src/security/tutorial004_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="7 49 56-57 60-61 70-76"
+ {!> ../../../docs_src/security/tutorial004_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="6 47 54-55 58-59 68-74"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7 48 55-56 59-60 69-75"
+ {!> ../../../docs_src/security/tutorial004.py!}
+ ```
+
!!! note
If you check the new (fake) database `fake_users_db`, you will see how the hashed password looks like now: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`.
@@ -152,18 +176,42 @@ Define a Pydantic Model that will be used in the token endpoint for the response
Create a utility function to generate a new access token.
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="6 12-14 28-30 78-86"
- {!> ../../../docs_src/security/tutorial004.py!}
+ {!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="6 12-14 28-30 78-86"
+ {!> ../../../docs_src/security/tutorial004_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="6 13-15 29-31 79-87"
+ {!> ../../../docs_src/security/tutorial004_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="5 11-13 27-29 77-85"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="6 12-14 28-30 78-86"
+ {!> ../../../docs_src/security/tutorial004.py!}
+ ```
+
## Update the dependencies
Update `get_current_user` to receive the same token as before, but this time, using JWT tokens.
@@ -172,36 +220,84 @@ Decode the received token, verify it, and return the current user.
If the token is invalid, return an HTTP error right away.
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python hl_lines="89-106"
- {!> ../../../docs_src/security/tutorial004.py!}
+ {!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="89-106"
+ {!> ../../../docs_src/security/tutorial004_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="90-107"
+ {!> ../../../docs_src/security/tutorial004_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="88-105"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="89-106"
+ {!> ../../../docs_src/security/tutorial004.py!}
+ ```
+
## Update the `/token` *path operation*
Create a `timedelta` with the expiration time of the token.
-Create a real JWT access token and return it.
+Create a real JWT access token and return it
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="115-128"
- {!> ../../../docs_src/security/tutorial004.py!}
+ ```Python hl_lines="117-132"
+ {!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="117-132"
+ {!> ../../../docs_src/security/tutorial004_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="118-133"
+ {!> ../../../docs_src/security/tutorial004_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="114-127"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="115-128"
+ {!> ../../../docs_src/security/tutorial004.py!}
+ ```
+
### Technical details about the JWT "subject" `sub`
The JWT specification says that there's a key `sub`, with the subject of the token.
diff --git a/docs/en/docs/tutorial/security/simple-oauth2.md b/docs/en/docs/tutorial/security/simple-oauth2.md
index 505b223b1..abcf6b667 100644
--- a/docs/en/docs/tutorial/security/simple-oauth2.md
+++ b/docs/en/docs/tutorial/security/simple-oauth2.md
@@ -49,18 +49,42 @@ Now let's use the utilities provided by **FastAPI** to handle this.
First, import `OAuth2PasswordRequestForm`, and use it as a dependency with `Depends` in the *path operation* for `/token`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="4 76"
- {!> ../../../docs_src/security/tutorial003.py!}
+ ```Python hl_lines="4 78"
+ {!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="4 78"
+ {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="4 79"
+ {!> ../../../docs_src/security/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="2 74"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="4 76"
+ {!> ../../../docs_src/security/tutorial003.py!}
+ ```
+
`OAuth2PasswordRequestForm` is a class dependency that declares a form body with:
* The `username`.
@@ -98,18 +122,42 @@ If there is no such user, we return an error saying "incorrect username or passw
For the error, we use the exception `HTTPException`:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="3 77-79"
- {!> ../../../docs_src/security/tutorial003.py!}
+ ```Python hl_lines="3 79-81"
+ {!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="3 79-81"
+ {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="3 80-82"
+ {!> ../../../docs_src/security/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="1 75-77"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="3 77-79"
+ {!> ../../../docs_src/security/tutorial003.py!}
+ ```
+
### Check the password
At this point we have the user data from our database, but we haven't checked the password.
@@ -134,18 +182,42 @@ If your database is stolen, the thief won't have your users' plaintext passwords
So, the thief won't be able to try to use those same passwords in another system (as many users use the same password everywhere, this would be dangerous).
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="80-83"
- {!> ../../../docs_src/security/tutorial003.py!}
+ ```Python hl_lines="82-85"
+ {!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="82-85"
+ {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="83-86"
+ {!> ../../../docs_src/security/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="78-81"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="80-83"
+ {!> ../../../docs_src/security/tutorial003.py!}
+ ```
+
#### About `**user_dict`
`UserInDB(**user_dict)` means:
@@ -180,18 +252,42 @@ For this simple example, we are going to just be completely insecure and return
But for now, let's focus on the specific details we need.
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="85"
- {!> ../../../docs_src/security/tutorial003.py!}
+ ```Python hl_lines="87"
+ {!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python hl_lines="87"
+ {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="88"
+ {!> ../../../docs_src/security/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="83"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="85"
+ {!> ../../../docs_src/security/tutorial003.py!}
+ ```
+
!!! tip
By the spec, you should return a JSON with an `access_token` and a `token_type`, the same as in this example.
@@ -213,18 +309,42 @@ Both of these dependencies will just return an HTTP error if the user doesn't ex
So, in our endpoint, we will only get a user if the user exists, was correctly authenticated, and is active:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
+
+ ```Python hl_lines="58-66 69-74 94"
+ {!> ../../../docs_src/security/tutorial003_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="58-66 69-74 94"
+ {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="59-67 70-75 95"
+ {!> ../../../docs_src/security/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="56-64 67-70 88"
+ {!> ../../../docs_src/security/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="58-66 69-72 90"
{!> ../../../docs_src/security/tutorial003.py!}
```
-=== "Python 3.10 and above"
-
- ```Python hl_lines="55-64 67-70 88"
- {!> ../../../docs_src/security/tutorial003_py310.py!}
- ```
-
!!! info
The additional header `WWW-Authenticate` with value `Bearer` we are returning here is also part of the spec.
diff --git a/docs/en/docs/tutorial/sql-databases.md b/docs/en/docs/tutorial/sql-databases.md
index 5ccaf05ec..fd66c5add 100644
--- a/docs/en/docs/tutorial/sql-databases.md
+++ b/docs/en/docs/tutorial/sql-databases.md
@@ -262,22 +262,22 @@ So, the user will also have a `password` when creating it.
But for security, the `password` won't be in other Pydantic *models*, for example, it won't be sent from the API when reading a user.
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="3 6-8 11-12 23-24 27-28"
- {!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
+ ```Python hl_lines="1 4-6 9-10 21-22 25-26"
+ {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="3 6-8 11-12 23-24 27-28"
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="1 4-6 9-10 21-22 25-26"
- {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
+ ```Python hl_lines="3 6-8 11-12 23-24 27-28"
+ {!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```
#### SQLAlchemy style and Pydantic style
@@ -306,22 +306,22 @@ The same way, when reading a user, we can now declare that `items` will contain
Not only the IDs of those items, but all the data that we defined in the Pydantic *model* for reading items: `Item`.
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="15-17 31-34"
- {!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
+ ```Python hl_lines="13-15 29-32"
+ {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="15-17 31-34"
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="13-15 29-32"
- {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
+ ```Python hl_lines="15-17 31-34"
+ {!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```
!!! tip
@@ -335,22 +335,22 @@ This ../../../docs_src/sql_databases/sql_app/schemas.py!}
+ ```Python hl_lines="13 17-18 29 34-35"
+ {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="15 19-20 31 36-37"
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="13 17-18 29 34-35"
- {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
+ ```Python hl_lines="15 19-20 31 36-37"
+ {!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```
!!! tip
@@ -481,18 +481,18 @@ And now in the file `sql_app/main.py` let's integrate and use all the other part
In a very simplistic way create the database tables:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="9"
- {!> ../../../docs_src/sql_databases/sql_app/main.py!}
- ```
-
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="7"
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/sql_databases/sql_app/main.py!}
+ ```
+
#### Alembic Note
Normally you would probably initialize your database (create tables, etc) with Alembic.
@@ -515,18 +515,18 @@ For that, we will create a new dependency with `yield`, as explained before in t
Our dependency will create a new SQLAlchemy `SessionLocal` that will be used in a single request, and then close it once the request is finished.
-=== "Python 3.6 and above"
-
- ```Python hl_lines="15-20"
- {!> ../../../docs_src/sql_databases/sql_app/main.py!}
- ```
-
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="13-18"
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="15-20"
+ {!> ../../../docs_src/sql_databases/sql_app/main.py!}
+ ```
+
!!! info
We put the creation of the `SessionLocal()` and handling of the requests in a `try` block.
@@ -540,18 +540,18 @@ And then, when using the dependency in a *path operation function*, we declare i
This will then give us better editor support inside the *path operation function*, because the editor will know that the `db` parameter is of type `Session`:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="24 32 38 47 53"
- {!> ../../../docs_src/sql_databases/sql_app/main.py!}
- ```
-
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="22 30 36 45 51"
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="24 32 38 47 53"
+ {!> ../../../docs_src/sql_databases/sql_app/main.py!}
+ ```
+
!!! info "Technical Details"
The parameter `db` is actually of type `SessionLocal`, but this class (created with `sessionmaker()`) is a "proxy" of a SQLAlchemy `Session`, so, the editor doesn't really know what methods are provided.
@@ -561,18 +561,18 @@ This will then give us better editor support inside the *path operation function
Now, finally, here's the standard **FastAPI** *path operations* code.
-=== "Python 3.6 and above"
-
- ```Python hl_lines="23-28 31-34 37-42 45-49 52-55"
- {!> ../../../docs_src/sql_databases/sql_app/main.py!}
- ```
-
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="21-26 29-32 35-40 43-47 50-53"
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="23-28 31-34 37-42 45-49 52-55"
+ {!> ../../../docs_src/sql_databases/sql_app/main.py!}
+ ```
+
We are creating the database session before each request in the dependency with `yield`, and then closing it afterwards.
And then we can create the required dependency in the *path operation function*, to get that session directly.
@@ -654,22 +654,22 @@ For example, in a background task worker with ../../../docs_src/sql_databases/sql_app/schemas.py!}
+ {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
```Python
- {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
+ {!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```
* `sql_app/crud.py`:
@@ -680,18 +680,18 @@ For example, in a background task worker with ../../../docs_src/sql_databases/sql_app/main.py!}
- ```
-
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
+=== "Python 3.6+"
+
+ ```Python
+ {!> ../../../docs_src/sql_databases/sql_app/main.py!}
+ ```
+
## Check it
You can copy this code and use it as is.
@@ -739,18 +739,18 @@ A "middleware" is basically a function that is always executed for each request,
The middleware we'll add (just a function) will create a new SQLAlchemy `SessionLocal` for each request, add it to the request and then close it once the request is finished.
-=== "Python 3.6 and above"
-
- ```Python hl_lines="14-22"
- {!> ../../../docs_src/sql_databases/sql_app/alt_main.py!}
- ```
-
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="12-20"
{!> ../../../docs_src/sql_databases/sql_app_py39/alt_main.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="14-22"
+ {!> ../../../docs_src/sql_databases/sql_app/alt_main.py!}
+ ```
+
!!! info
We put the creation of the `SessionLocal()` and handling of the requests in a `try` block.
diff --git a/docs/en/docs/tutorial/testing.md b/docs/en/docs/tutorial/testing.md
index be07aab37..ec133a4d0 100644
--- a/docs/en/docs/tutorial/testing.md
+++ b/docs/en/docs/tutorial/testing.md
@@ -110,18 +110,42 @@ It has a `POST` operation that could return several errors.
Both *path operations* require an `X-Token` header.
-=== "Python 3.6 and above"
+=== "Python 3.10+"
```Python
- {!> ../../../docs_src/app_testing/app_b/main.py!}
+ {!> ../../../docs_src/app_testing/app_b_an_py310/main.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.9+"
+
+ ```Python
+ {!> ../../../docs_src/app_testing/app_b_an_py39/main.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python
+ {!> ../../../docs_src/app_testing/app_b_an/main.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python
{!> ../../../docs_src/app_testing/app_b_py310/main.py!}
```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python
+ {!> ../../../docs_src/app_testing/app_b/main.py!}
+ ```
+
### Extended testing file
You could then update `test_main.py` with the extended tests:
diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml
index a5d77acbf..fc21439ae 100644
--- a/docs/en/mkdocs.yml
+++ b/docs/en/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -212,6 +213,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html
index b85f0c4cf..9125b1d46 100644
--- a/docs/en/overrides/main.html
+++ b/docs/en/overrides/main.html
@@ -22,24 +22,12 @@
{% endblock %}
diff --git a/docs/es/mkdocs.yml b/docs/es/mkdocs.yml
index a89aeb21a..485a2dd70 100644
--- a/docs/es/mkdocs.yml
+++ b/docs/es/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -115,6 +116,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/fa/docs/index.md b/docs/fa/docs/index.md
index dfc4d24e3..ebaa8085a 100644
--- a/docs/fa/docs/index.md
+++ b/docs/fa/docs/index.md
@@ -143,7 +143,7 @@ $ pip install "uvicorn[standard]"
* فایلی به نام `main.py` با محتوای زیر ایجاد کنید :
```Python
-from typing import Optional
+from typing import Union
from fastapi import FastAPI
diff --git a/docs/fa/mkdocs.yml b/docs/fa/mkdocs.yml
index f77f82f69..914b46e1a 100644
--- a/docs/fa/mkdocs.yml
+++ b/docs/fa/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -105,6 +106,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/fr/docs/advanced/index.md b/docs/fr/docs/advanced/index.md
new file mode 100644
index 000000000..41737889a
--- /dev/null
+++ b/docs/fr/docs/advanced/index.md
@@ -0,0 +1,24 @@
+# Guide de l'utilisateur avancé - Introduction
+
+## Caractéristiques supplémentaires
+
+Le [Tutoriel - Guide de l'utilisateur](../tutorial/){.internal-link target=_blank} devrait suffire à vous faire découvrir toutes les fonctionnalités principales de **FastAPI**.
+
+Dans les sections suivantes, vous verrez des options, configurations et fonctionnalités supplémentaires.
+
+!!! Note
+ Les sections de ce chapitre ne sont **pas nécessairement "avancées"**.
+
+ Et il est possible que pour votre cas d'utilisation, la solution se trouve dans l'un d'entre eux.
+
+## Lisez d'abord le didacticiel
+
+Vous pouvez utiliser la plupart des fonctionnalités de **FastAPI** grâce aux connaissances du [Tutoriel - Guide de l'utilisateur](../tutorial/){.internal-link target=_blank}.
+
+Et les sections suivantes supposent que vous l'avez lu et que vous en connaissez les idées principales.
+
+## Cours TestDriven.io
+
+Si vous souhaitez suivre un cours pour débutants avancés pour compléter cette section de la documentation, vous pouvez consulter : Développement piloté par les tests avec FastAPI et Docker par **TestDriven.io**.
+
+10 % de tous les bénéfices de ce cours sont reversés au développement de **FastAPI**. 🎉 😄
diff --git a/docs/fr/docs/index.md b/docs/fr/docs/index.md
index e7fb9947d..5ee8b462f 100644
--- a/docs/fr/docs/index.md
+++ b/docs/fr/docs/index.md
@@ -1,48 +1,46 @@
-
-{!../../../docs/missing-translation.md!}
-
-
- FastAPI framework, high performance, easy to learn, fast to code, ready for production + Framework FastAPI, haute performance, facile à apprendre, rapide à coder, prêt pour la production
--- -**Documentation**: https://fastapi.tiangolo.com +**Documentation** : https://fastapi.tiangolo.com -**Source Code**: https://github.com/tiangolo/fastapi +**Code Source** : https://github.com/tiangolo/fastapi --- -FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints. +FastAPI est un framework web moderne et rapide (haute performance) pour la création d'API avec Python 3.7+, basé sur les annotations de type standard de Python. -The key features are: +Les principales fonctionnalités sont : -* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance). +* **Rapidité** : De très hautes performances, au niveau de **NodeJS** et **Go** (grâce à Starlette et Pydantic). [L'un des frameworks Python les plus rapides](#performance). +* **Rapide à coder** : Augmente la vitesse de développement des fonctionnalités d'environ 200 % à 300 %. * +* **Moins de bugs** : Réduit d'environ 40 % les erreurs induites par le développeur. * +* **Intuitif** : Excellente compatibilité avec les IDE. Complétion complète. Moins de temps passé à déboguer. +* **Facile** : Conçu pour être facile à utiliser et à apprendre. Moins de temps passé à lire la documentation. +* **Concis** : Diminue la duplication de code. De nombreuses fonctionnalités liées à la déclaration de chaque paramètre. Moins de bugs. +* **Robuste** : Obtenez un code prêt pour la production. Avec une documentation interactive automatique. +* **Basé sur des normes** : Basé sur (et entièrement compatible avec) les standards ouverts pour les APIs : OpenAPI (précédemment connu sous le nom de Swagger) et JSON Schema. -* **Fast to code**: Increase the speed to develop features by about 200% to 300%. * -* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. * -* **Intuitive**: Great editor support. Completion everywhere. Less time debugging. -* **Easy**: Designed to be easy to use and learn. Less time reading docs. -* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. -* **Robust**: Get production-ready code. With automatic interactive documentation. -* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: OpenAPI (previously known as Swagger) and JSON Schema. - -* estimation based on tests on an internal development team, building production applications. +* estimation basée sur des tests d'une équipe de développement interne, construisant des applications de production. ## Sponsors @@ -63,60 +61,66 @@ The key features are: ## Opinions -"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._" +"_[...] J'utilise beaucoup **FastAPI** ces derniers temps. [...] Je prévois de l'utiliser dans mon équipe pour tous les **services de ML chez Microsoft**. Certains d'entre eux seront intégrés dans le coeur de **Windows** et dans certains produits **Office**._"async def...async def ...uvicorn main:app --reload...uvicorn main:app --reload ...ujson - for faster JSON "parsing".
-* email_validator - for email validation.
+* ujson - pour un "décodage" JSON plus rapide.
+* email_validator - pour la validation des adresses email.
-Used by Starlette:
+Utilisées par Starlette :
-* HTTPX - Required if you want to use the `TestClient`.
-* jinja2 - Required if you want to use the default template configuration.
-* python-multipart - Required if you want to support form "parsing", with `request.form()`.
-* itsdangerous - Required for `SessionMiddleware` support.
-* pyyaml - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI).
-* graphene - Required for `GraphQLApp` support.
-* ujson - Required if you want to use `UJSONResponse`.
+* requests - Obligatoire si vous souhaitez utiliser `TestClient`.
+* jinja2 - Obligatoire si vous souhaitez utiliser la configuration de template par defaut.
+* python-multipart - Obligatoire si vous souhaitez supporter le "décodage" de formulaire avec `request.form()`.
+* itsdangerous - Obligatoire pour la prise en charge de `SessionMiddleware`.
+* pyyaml - Obligatoire pour le support `SchemaGenerator` de Starlette (vous n'en avez probablement pas besoin avec FastAPI).
+* ujson - Obligatoire si vous souhaitez utiliser `UJSONResponse`.
-Used by FastAPI / Starlette:
+Utilisées par FastAPI / Starlette :
-* uvicorn - for the server that loads and serves your application.
-* orjson - Required if you want to use `ORJSONResponse`.
+* uvicorn - Pour le serveur qui charge et sert votre application.
+* orjson - Obligatoire si vous voulez utiliser `ORJSONResponse`.
-You can install all of these with `pip install fastapi[all]`.
+Vous pouvez tout installer avec `pip install fastapi[all]`.
-## License
+## Licence
-This project is licensed under the terms of the MIT license.
+Ce projet est soumis aux termes de la licence MIT.
diff --git a/docs/fr/mkdocs.yml b/docs/fr/mkdocs.yml
index 19182f381..36fbfb2d0 100644
--- a/docs/fr/mkdocs.yml
+++ b/docs/fr/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -71,6 +72,7 @@ nav:
- tutorial/background-tasks.md
- tutorial/debugging.md
- Guide utilisateur avancé:
+ - advanced/index.md
- advanced/path-operation-advanced-configuration.md
- advanced/additional-status-codes.md
- advanced/additional-responses.md
@@ -132,6 +134,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/he/mkdocs.yml b/docs/he/mkdocs.yml
index c5689395f..094c5d82e 100644
--- a/docs/he/mkdocs.yml
+++ b/docs/he/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -105,6 +106,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/hy/mkdocs.yml b/docs/hy/mkdocs.yml
index bc64e78f2..ba7c687c1 100644
--- a/docs/hy/mkdocs.yml
+++ b/docs/hy/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -56,6 +57,7 @@ nav:
- ru: /ru/
- sq: /sq/
- sv: /sv/
+ - ta: /ta/
- tr: /tr/
- uk: /uk/
- zh: /zh/
@@ -81,7 +83,7 @@ markdown_extensions:
extra:
analytics:
provider: google
- property: UA-133183413-1
+ property: G-YNEVN69SC3
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
@@ -104,6 +106,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
@@ -134,6 +138,8 @@ extra:
name: sq - shqip
- link: /sv/
name: sv - svenska
+ - link: /ta/
+ name: ta - தமிழ்
- link: /tr/
name: tr - Türkçe
- link: /uk/
diff --git a/docs/id/mkdocs.yml b/docs/id/mkdocs.yml
index 7b7875ef7..ca6e09551 100644
--- a/docs/id/mkdocs.yml
+++ b/docs/id/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -105,6 +106,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/it/mkdocs.yml b/docs/it/mkdocs.yml
index 9393c3663..4633dd017 100644
--- a/docs/it/mkdocs.yml
+++ b/docs/it/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -105,6 +106,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/ja/docs/tutorial/testing.md b/docs/ja/docs/tutorial/testing.md
index 56f5cabac..037e9628f 100644
--- a/docs/ja/docs/tutorial/testing.md
+++ b/docs/ja/docs/tutorial/testing.md
@@ -74,18 +74,18 @@
これらの *path operation* には `X-Token` ヘッダーが必要です。
-=== "Python 3.6 and above"
-
- ```Python
- {!> ../../../docs_src/app_testing/app_b/main.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python
{!> ../../../docs_src/app_testing/app_b_py310/main.py!}
```
+=== "Python 3.6+"
+
+ ```Python
+ {!> ../../../docs_src/app_testing/app_b/main.py!}
+ ```
+
### 拡張版テストファイル
次に、先程のものに拡張版のテストを加えた、`test_main_b.py` を作成します。
diff --git a/docs/ja/mkdocs.yml b/docs/ja/mkdocs.yml
index 3703398af..9f4342e76 100644
--- a/docs/ja/mkdocs.yml
+++ b/docs/ja/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -149,6 +150,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/ko/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/ko/docs/tutorial/dependencies/classes-as-dependencies.md
new file mode 100644
index 000000000..bbf3a8283
--- /dev/null
+++ b/docs/ko/docs/tutorial/dependencies/classes-as-dependencies.md
@@ -0,0 +1,244 @@
+# 의존성으로서의 클래스
+
+**의존성 주입** 시스템에 대해 자세히 살펴보기 전에 이전 예제를 업그레이드 해보겠습니다.
+
+## 이전 예제의 `딕셔너리`
+
+이전 예제에서, 우리는 의존성(의존 가능한) 함수에서 `딕셔너리`객체를 반환하고 있었습니다:
+
+=== "파이썬 3.6 이상"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
+=== "파이썬 3.10 이상"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/dependencies/tutorial001_py310.py!}
+ ```
+
+우리는 *경로 작동 함수*의 매개변수 `commons`에서 `딕셔너리` 객체를 얻습니다.
+
+그리고 우리는 에디터들이 `딕셔너리` 객체의 키나 밸류의 자료형을 알 수 없기 때문에 자동 완성과 같은 기능을 제공해 줄 수 없다는 것을 알고 있습니다.
+
+더 나은 방법이 있을 것 같습니다...
+
+## 의존성으로 사용 가능한 것
+
+지금까지 함수로 선언된 의존성을 봐왔습니다.
+
+아마도 더 일반적이기는 하겠지만 의존성을 선언하는 유일한 방법은 아닙니다.
+
+핵심 요소는 의존성이 "호출 가능"해야 한다는 것입니다
+
+파이썬에서의 "**호출 가능**"은 파이썬이 함수처럼 "호출"할 수 있는 모든 것입니다.
+
+따라서, 만약 당신이 `something`(함수가 아닐 수도 있음) 객체를 가지고 있고,
+
+```Python
+something()
+```
+
+또는
+
+```Python
+something(some_argument, some_keyword_argument="foo")
+```
+
+상기와 같은 방식으로 "호출(실행)" 할 수 있다면 "호출 가능"이 됩니다.
+
+## 의존성으로서의 클래스
+
+파이썬 클래스의 인스턴스를 생성하기 위해 사용하는 것과 동일한 문법을 사용한다는 걸 알 수 있습니다.
+
+예를 들어:
+
+```Python
+class Cat:
+ def __init__(self, name: str):
+ self.name = name
+
+
+fluffy = Cat(name="Mr Fluffy")
+```
+
+이 경우에 `fluffy`는 클래스 `Cat`의 인스턴스입니다. 그리고 우리는 `fluffy`를 만들기 위해서 `Cat`을 "호출"했습니다.
+
+따라서, 파이썬 클래스는 **호출 가능**합니다.
+
+그래서 **FastAPI**에서는 파이썬 클래스를 의존성으로 사용할 수 있습니다.
+
+FastAPI가 실질적으로 확인하는 것은 "호출 가능성"(함수, 클래스 또는 다른 모든 것)과 정의된 매개변수들입니다.
+
+"호출 가능"한 것을 의존성으로서 **FastAPI**에 전달하면, 그 "호출 가능"한 것의 매개변수들을 분석한 후 이를 *경로 동작 함수*를 위한 매개변수와 동일한 방식으로 처리합니다. 하위-의존성 또한 같은 방식으로 처리합니다.
+
+매개변수가 없는 "호출 가능"한 것 역시 매개변수가 없는 *경로 동작 함수*와 동일한 방식으로 적용됩니다.
+
+그래서, 우리는 위 예제에서의 `common_paramenters` 의존성을 클래스 `CommonQueryParams`로 바꿀 수 있습니다.
+
+=== "파이썬 3.6 이상"
+
+ ```Python hl_lines="11-15"
+ {!> ../../../docs_src/dependencies/tutorial002.py!}
+ ```
+
+=== "파이썬 3.10 이상"
+
+ ```Python hl_lines="9-13"
+ {!> ../../../docs_src/dependencies/tutorial002_py310.py!}
+ ```
+
+클래스의 인스턴스를 생성하는 데 사용되는 `__init__` 메서드에 주목하기 바랍니다:
+
+=== "파이썬 3.6 이상"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/dependencies/tutorial002.py!}
+ ```
+
+=== "파이썬 3.10 이상"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/dependencies/tutorial002_py310.py!}
+ ```
+
+...이전 `common_parameters`와 동일한 매개변수를 가집니다:
+
+=== "파이썬 3.6 이상"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
+=== "파이썬 3.10 이상"
+
+ ```Python hl_lines="6"
+ {!> ../../../docs_src/dependencies/tutorial001_py310.py!}
+ ```
+
+이 매개변수들은 **FastAPI**가 의존성을 "해결"하기 위해 사용할 것입니다
+
+함수와 클래스 두 가지 방식 모두, 아래 요소를 갖습니다:
+
+* `문자열`이면서 선택사항인 쿼리 매개변수 `q`.
+* 기본값이 `0`이면서 `정수형`인 쿼리 매개변수 `skip`
+* 기본값이 `100`이면서 `정수형`인 쿼리 매개변수 `limit`
+
+두 가지 방식 모두, 데이터는 변환, 검증되고 OpenAPI 스키마에 문서화됩니다.
+
+## 사용해봅시다!
+
+이제 아래의 클래스를 이용해서 의존성을 정의할 수 있습니다.
+
+=== "파이썬 3.6 이상"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial002.py!}
+ ```
+
+=== "파이썬 3.10 이상"
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/dependencies/tutorial002_py310.py!}
+ ```
+
+**FastAPI**는 `CommonQueryParams` 클래스를 호출합니다. 이것은 해당 클래스의 "인스턴스"를 생성하고 그 인스턴스는 함수의 매개변수 `commons`로 전달됩니다.
+
+## 타입 힌팅 vs `Depends`
+
+위 코드에서 `CommonQueryParams`를 두 번 작성한 방식에 주목하십시오:
+
+```Python
+commons: CommonQueryParams = Depends(CommonQueryParams)
+```
+
+마지막 `CommonQueryParams` 변수를 보면:
+
+```Python
+... = Depends(CommonQueryParams)
+```
+
+... **FastAPI**가 실제로 어떤 것이 의존성인지 알기 위해서 사용하는 방법입니다.
+FastAPI는 선언된 매개변수들을 추출할 것이고 실제로 이 변수들을 호출할 것입니다.
+
+---
+
+이 경우에, 첫번째 `CommonQueryParams` 변수를 보면:
+
+```Python
+commons: CommonQueryParams ...
+```
+
+... **FastAPI**는 `CommonQueryParams` 변수에 어떠한 특별한 의미도 부여하지 않습니다. FastAPI는 이 변수를 데이터 변환, 검증 등에 활용하지 않습니다. (활용하려면 `= Depends(CommonQueryParams)`를 사용해야 합니다.)
+
+사실 아래와 같이 작성해도 무관합니다:
+
+```Python
+commons = Depends(CommonQueryParams)
+```
+
+..전체적인 코드는 아래와 같습니다:
+
+=== "파이썬 3.6 이상"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial003.py!}
+ ```
+
+=== "파이썬 3.10 이상"
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/dependencies/tutorial003_py310.py!}
+ ```
+
+그러나 자료형을 선언하면 에디터가 매개변수 `commons`로 전달될 것이 무엇인지 알게 되고, 이를 통해 코드 완성, 자료형 확인 등에 도움이 될 수 있으므로 권장됩니다.
+
+
+
+## 코드 단축
+
+그러나 여기 `CommonQueryParams`를 두 번이나 작성하는, 코드 반복이 있다는 것을 알 수 있습니다:
+
+```Python
+commons: CommonQueryParams = Depends(CommonQueryParams)
+```
+
+**FastAPI**는 *특히* 의존성이 **FastAPI**가 클래스 자체의 인스턴스를 생성하기 위해 "호출"하는 클래스인 경우, 조금 더 쉬운 방법을 제공합니다.
+
+이러한 특정한 경우에는 아래처럼 사용할 수 있습니다:
+
+이렇게 쓰는 것 대신:
+
+```Python
+commons: CommonQueryParams = Depends(CommonQueryParams)
+```
+
+...이렇게 쓸 수 있습니다.:
+
+```Python
+commons: CommonQueryParams = Depends()
+```
+
+의존성을 매개변수의 타입으로 선언하는 경우 `Depends(CommonQueryParams)`처럼 클래스 이름 전체를 *다시* 작성하는 대신, 매개변수를 넣지 않은 `Depends()`의 형태로 사용할 수 있습니다.
+
+아래에 같은 예제가 있습니다:
+
+=== "파이썬 3.6 이상"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial004.py!}
+ ```
+
+=== "파이썬 3.10 이상"
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/dependencies/tutorial004_py310.py!}
+ ```
+
+...이렇게 코드를 단축하여도 **FastAPI**는 무엇을 해야하는지 알고 있습니다.
+
+!!! tip "팁"
+ 만약 이것이 도움이 되기보다 더 헷갈리게 만든다면, 잊어버리십시오. 이것이 반드시 필요한 것은 아닙니다.
+
+ 이것은 단지 손쉬운 방법일 뿐입니다. 왜냐하면 **FastAPI**는 코드 반복을 최소화할 수 있는 방법을 고민하기 때문입니다.
diff --git a/docs/ko/mkdocs.yml b/docs/ko/mkdocs.yml
index 29b684371..1ab63e791 100644
--- a/docs/ko/mkdocs.yml
+++ b/docs/ko/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -72,6 +73,8 @@ nav:
- tutorial/request-forms-and-files.md
- tutorial/encoder.md
- tutorial/cors.md
+ - 의존성:
+ - tutorial/dependencies/classes-as-dependencies.md
markdown_extensions:
- toc:
permalink: true
@@ -117,6 +120,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/nl/mkdocs.yml b/docs/nl/mkdocs.yml
index d9b1bc1b8..e187ee383 100644
--- a/docs/nl/mkdocs.yml
+++ b/docs/nl/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -105,6 +106,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/pl/mkdocs.yml b/docs/pl/mkdocs.yml
index 8d0d20239..c781f9783 100644
--- a/docs/pl/mkdocs.yml
+++ b/docs/pl/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -108,6 +109,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/pt/docs/tutorial/body-multiple-params.md b/docs/pt/docs/tutorial/body-multiple-params.md
index ac67aa47f..22f5856a6 100644
--- a/docs/pt/docs/tutorial/body-multiple-params.md
+++ b/docs/pt/docs/tutorial/body-multiple-params.md
@@ -8,18 +8,18 @@ Primeiro, é claro, você pode misturar `Path`, `Query` e declarações de parâ
E você também pode declarar parâmetros de corpo como opcionais, definindo o valor padrão com `None`:
-=== "Python 3.6 e superiores"
-
- ```Python hl_lines="19-21"
- {!> ../../../docs_src/body_multiple_params/tutorial001.py!}
- ```
-
-=== "Python 3.10 e superiores"
+=== "Python 3.10+"
```Python hl_lines="17-19"
{!> ../../../docs_src/body_multiple_params/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="19-21"
+ {!> ../../../docs_src/body_multiple_params/tutorial001.py!}
+ ```
+
!!! nota
Repare que, neste caso, o `item` que seria capturado a partir do corpo é opcional. Visto que ele possui `None` como valor padrão.
@@ -38,18 +38,18 @@ No exemplo anterior, as *operações de rota* esperariam um JSON no corpo conten
Mas você pode também declarar múltiplos parâmetros de corpo, por exemplo, `item` e `user`:
-=== "Python 3.6 e superiores"
-
- ```Python hl_lines="22"
- {!> ../../../docs_src/body_multiple_params/tutorial002.py!}
- ```
-
-=== "Python 3.10 e superiores"
+=== "Python 3.10+"
```Python hl_lines="20"
{!> ../../../docs_src/body_multiple_params/tutorial002_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/body_multiple_params/tutorial002.py!}
+ ```
+
Neste caso, o **FastAPI** perceberá que existe mais de um parâmetro de corpo na função (dois parâmetros que são modelos Pydantic).
Então, ele usará o nome dos parâmetros como chaves (nome dos campos) no corpo, e espera um corpo como:
@@ -87,13 +87,13 @@ Se você declará-lo como é, porque é um valor singular, o **FastAPI** assumir
Mas você pode instruir o **FastAPI** para tratá-lo como outra chave do corpo usando `Body`:
-=== "Python 3.6 e superiores"
+=== "Python 3.6+"
```Python hl_lines="22"
{!> ../../../docs_src/body_multiple_params/tutorial003.py!}
```
-=== "Python 3.10 e superiores"
+=== "Python 3.10+"
```Python hl_lines="20"
{!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!}
@@ -137,18 +137,18 @@ q: str | None = None
Por exemplo:
-=== "Python 3.6 e superiores"
-
- ```Python hl_lines="27"
- {!> ../../../docs_src/body_multiple_params/tutorial004.py!}
- ```
-
-=== "Python 3.10 e superiores"
+=== "Python 3.10+"
```Python hl_lines="26"
{!> ../../../docs_src/body_multiple_params/tutorial004_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="27"
+ {!> ../../../docs_src/body_multiple_params/tutorial004.py!}
+ ```
+
!!! info "Informação"
`Body` também possui todas as validações adicionais e metadados de parâmetros como em `Query`,`Path` e outras que você verá depois.
@@ -166,18 +166,18 @@ item: Item = Body(embed=True)
como em:
-=== "Python 3.6 e superiores"
-
- ```Python hl_lines="17"
- {!> ../../../docs_src/body_multiple_params/tutorial005.py!}
- ```
-
-=== "Python 3.10 e superiores"
+=== "Python 3.10+"
```Python hl_lines="15"
{!> ../../../docs_src/body_multiple_params/tutorial005_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/body_multiple_params/tutorial005.py!}
+ ```
+
Neste caso o **FastAPI** esperará um corpo como:
```JSON hl_lines="2"
diff --git a/docs/pt/docs/tutorial/body-nested-models.md b/docs/pt/docs/tutorial/body-nested-models.md
new file mode 100644
index 000000000..8ab77173e
--- /dev/null
+++ b/docs/pt/docs/tutorial/body-nested-models.md
@@ -0,0 +1,248 @@
+# Corpo - Modelos aninhados
+
+Com o **FastAPI**, você pode definir, validar, documentar e usar modelos profundamente aninhados de forma arbitrária (graças ao Pydantic).
+
+## Campos do tipo Lista
+
+Você pode definir um atributo como um subtipo. Por exemplo, uma `list` do Python:
+
+```Python hl_lines="14"
+{!../../../docs_src/body_nested_models/tutorial001.py!}
+```
+
+Isso fará com que tags seja uma lista de itens mesmo sem declarar o tipo dos elementos desta lista.
+
+## Campos do tipo Lista com um parâmetro de tipo
+
+Mas o Python tem uma maneira específica de declarar listas com tipos internos ou "parâmetros de tipo":
+
+### Importe `List` do typing
+
+Primeiramente, importe `List` do módulo `typing` que já vem por padrão no Python:
+
+```Python hl_lines="1"
+{!../../../docs_src/body_nested_models/tutorial002.py!}
+```
+
+### Declare a `List` com um parâmetro de tipo
+
+Para declarar tipos que têm parâmetros de tipo(tipos internos), como `list`, `dict`, `tuple`:
+
+* Importe os do modulo `typing`
+* Passe o(s) tipo(s) interno(s) como "parâmetros de tipo" usando colchetes: `[` e `]`
+
+```Python
+from typing import List
+
+my_list: List[str]
+```
+
+Essa é a sintaxe padrão do Python para declarações de tipo.
+
+Use a mesma sintaxe padrão para atributos de modelo com tipos internos.
+
+Portanto, em nosso exemplo, podemos fazer com que `tags` sejam especificamente uma "lista de strings":
+
+
+```Python hl_lines="14"
+{!../../../docs_src/body_nested_models/tutorial002.py!}
+```
+
+## Tipo "set"
+
+
+Mas então, quando nós pensamos mais, percebemos que as tags não devem se repetir, elas provavelmente devem ser strings únicas.
+
+E que o Python tem um tipo de dados especial para conjuntos de itens únicos, o `set`.
+
+Então podemos importar `Set` e declarar `tags` como um `set` de `str`s:
+
+
+```Python hl_lines="1 14"
+{!../../../docs_src/body_nested_models/tutorial003.py!}
+```
+
+Com isso, mesmo que você receba uma requisição contendo dados duplicados, ela será convertida em um conjunto de itens exclusivos.
+
+E sempre que você enviar esses dados como resposta, mesmo se a fonte tiver duplicatas, eles serão gerados como um conjunto de itens exclusivos.
+
+E também teremos anotações/documentação em conformidade.
+
+## Modelos aninhados
+
+Cada atributo de um modelo Pydantic tem um tipo.
+
+Mas esse tipo pode ser outro modelo Pydantic.
+
+Portanto, você pode declarar "objects" JSON profundamente aninhados com nomes, tipos e validações de atributos específicos.
+
+Tudo isso, aninhado arbitrariamente.
+
+### Defina um sub-modelo
+
+Por exemplo, nós podemos definir um modelo `Image`:
+
+```Python hl_lines="9-11"
+{!../../../docs_src/body_nested_models/tutorial004.py!}
+```
+
+### Use o sub-modelo como um tipo
+
+E então podemos usa-lo como o tipo de um atributo:
+
+```Python hl_lines="20"
+{!../../../docs_src/body_nested_models/tutorial004.py!}
+```
+
+Isso significa que o **FastAPI** vai esperar um corpo similar à:
+
+```JSON
+{
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2,
+ "tags": ["rock", "metal", "bar"],
+ "image": {
+ "url": "http://example.com/baz.jpg",
+ "name": "The Foo live"
+ }
+}
+```
+
+Novamente, apenas fazendo essa declaração, com o **FastAPI**, você ganha:
+
+* Suporte do editor de texto (compleção, etc), inclusive para modelos aninhados
+* Conversão de dados
+* Validação de dados
+* Documentação automatica
+
+## Tipos especiais e validação
+
+Além dos tipos singulares normais como `str`, `int`, `float`, etc. Você também pode usar tipos singulares mais complexos que herdam de `str`.
+
+Para ver todas as opções possíveis, cheque a documentação para ostipos exoticos do Pydantic. Você verá alguns exemplos no próximo capitulo.
+
+Por exemplo, no modelo `Image` nós temos um campo `url`, nós podemos declara-lo como um `HttpUrl` do Pydantic invés de como uma `str`:
+
+```Python hl_lines="4 10"
+{!../../../docs_src/body_nested_models/tutorial005.py!}
+```
+
+A string será verificada para se tornar uma URL válida e documentada no esquema JSON/1OpenAPI como tal.
+
+## Atributos como listas de submodelos
+
+Você também pode usar modelos Pydantic como subtipos de `list`, `set`, etc:
+
+```Python hl_lines="20"
+{!../../../docs_src/body_nested_models/tutorial006.py!}
+```
+
+Isso vai esperar(converter, validar, documentar, etc) um corpo JSON tal qual:
+
+```JSON hl_lines="11"
+{
+ "name": "Foo",
+ "description": "The pretender",
+ "price": 42.0,
+ "tax": 3.2,
+ "tags": [
+ "rock",
+ "metal",
+ "bar"
+ ],
+ "images": [
+ {
+ "url": "http://example.com/baz.jpg",
+ "name": "The Foo live"
+ },
+ {
+ "url": "http://example.com/dave.jpg",
+ "name": "The Baz"
+ }
+ ]
+}
+```
+
+!!! Informação
+ Note como o campo `images` agora tem uma lista de objetos de image.
+
+## Modelos profundamente aninhados
+
+Você pode definir modelos profundamente aninhados de forma arbitrária:
+
+```Python hl_lines="9 14 20 23 27"
+{!../../../docs_src/body_nested_models/tutorial007.py!}
+```
+
+!!! Informação
+ Note como `Offer` tem uma lista de `Item`s, que por sua vez possui opcionalmente uma lista `Image`s
+
+## Corpos de listas puras
+
+Se o valor de primeiro nível do corpo JSON que você espera for um `array` do JSON (uma` lista` do Python), você pode declarar o tipo no parâmetro da função, da mesma forma que nos modelos do Pydantic:
+
+
+```Python
+images: List[Image]
+```
+
+como em:
+
+```Python hl_lines="15"
+{!../../../docs_src/body_nested_models/tutorial008.py!}
+```
+
+## Suporte de editor em todo canto
+
+E você obtém suporte do editor em todos os lugares.
+
+Mesmo para itens dentro de listas:
+
+
+
+Você não conseguiria este tipo de suporte de editor se estivesse trabalhando diretamente com `dict` em vez de modelos Pydantic.
+
+Mas você também não precisa se preocupar com eles, os dicts de entrada são convertidos automaticamente e sua saída é convertida automaticamente para JSON também.
+
+## Corpos de `dict`s arbitrários
+
+Você também pode declarar um corpo como um `dict` com chaves de algum tipo e valores de outro tipo.
+
+Sem ter que saber de antemão quais são os nomes de campos/atributos válidos (como seria o caso dos modelos Pydantic).
+
+Isso seria útil se você deseja receber chaves que ainda não conhece.
+
+---
+
+Outro caso útil é quando você deseja ter chaves de outro tipo, por exemplo, `int`.
+
+É isso que vamos ver aqui.
+
+Neste caso, você aceitaria qualquer `dict`, desde que tenha chaves` int` com valores `float`:
+
+```Python hl_lines="9"
+{!../../../docs_src/body_nested_models/tutorial009.py!}
+```
+
+!!! Dica
+ Leve em condideração que o JSON só suporta `str` como chaves.
+
+ Mas o Pydantic tem conversão automática de dados.
+
+ Isso significa que, embora os clientes da API só possam enviar strings como chaves, desde que essas strings contenham inteiros puros, o Pydantic irá convertê-los e validá-los.
+
+ E o `dict` que você recebe como `weights` terá, na verdade, chaves `int` e valores` float`.
+
+## Recapitulação
+
+Com **FastAPI** você tem a flexibilidade máxima fornecida pelos modelos Pydantic, enquanto seu código é mantido simples, curto e elegante.
+
+Mas com todos os benefícios:
+
+* Suporte do editor (compleção em todo canto!)
+* Conversão de dados (leia-se parsing/serialização)
+* Validação de dados
+* Documentação dos esquemas
+* Documentação automática
diff --git a/docs/pt/docs/tutorial/encoder.md b/docs/pt/docs/tutorial/encoder.md
index bb04e9ca2..bb4483fdc 100644
--- a/docs/pt/docs/tutorial/encoder.md
+++ b/docs/pt/docs/tutorial/encoder.md
@@ -20,18 +20,18 @@ Você pode usar a função `jsonable_encoder` para resolver isso.
A função recebe um objeto, como um modelo Pydantic e retorna uma versão compatível com JSON:
-=== "Python 3.6 e acima"
-
- ```Python hl_lines="5 22"
- {!> ../../../docs_src/encoder/tutorial001.py!}
- ```
-
-=== "Python 3.10 e acima"
+=== "Python 3.10+"
```Python hl_lines="4 21"
{!> ../../../docs_src/encoder/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="5 22"
+ {!> ../../../docs_src/encoder/tutorial001.py!}
+ ```
+
Neste exemplo, ele converteria o modelo Pydantic em um `dict`, e o `datetime` em um `str`.
O resultado de chamar a função é algo que pode ser codificado com o padrão do Python `json.dumps()`.
diff --git a/docs/pt/docs/tutorial/extra-models.md b/docs/pt/docs/tutorial/extra-models.md
new file mode 100644
index 000000000..dd5407eb2
--- /dev/null
+++ b/docs/pt/docs/tutorial/extra-models.md
@@ -0,0 +1,252 @@
+# Modelos Adicionais
+
+Continuando com o exemplo anterior, será comum ter mais de um modelo relacionado.
+
+Isso é especialmente o caso para modelos de usuários, porque:
+
+* O **modelo de entrada** precisa ser capaz de ter uma senha.
+* O **modelo de saída** não deve ter uma senha.
+* O **modelo de banco de dados** provavelmente precisaria ter uma senha criptografada.
+
+!!! danger
+ Nunca armazene senhas em texto simples dos usuários. Sempre armazene uma "hash segura" que você pode verificar depois.
+
+ Se não souber, você aprenderá o que é uma "senha hash" nos [capítulos de segurança](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}.
+
+## Múltiplos modelos
+
+Aqui está uma ideia geral de como os modelos poderiam parecer com seus campos de senha e os lugares onde são usados:
+
+=== "Python 3.6 and above"
+
+ ```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
+ {!> ../../../docs_src/extra_models/tutorial001.py!}
+ ```
+
+=== "Python 3.10 and above"
+
+ ```Python hl_lines="7 9 14 20 22 27-28 31-33 38-39"
+ {!> ../../../docs_src/extra_models/tutorial001_py310.py!}
+ ```
+
+### Sobre `**user_in.dict()`
+
+#### O `.dict()` do Pydantic
+
+`user_in` é um modelo Pydantic da classe `UserIn`.
+
+Os modelos Pydantic possuem um método `.dict()` que retorna um `dict` com os dados do modelo.
+
+Então, se criarmos um objeto Pydantic `user_in` como:
+
+```Python
+user_in = UserIn(username="john", password="secret", email="john.doe@example.com")
+```
+
+e depois chamarmos:
+
+```Python
+user_dict = user_in.dict()
+```
+
+agora temos um `dict` com os dados na variável `user_dict` (é um `dict` em vez de um objeto de modelo Pydantic).
+
+E se chamarmos:
+
+```Python
+print(user_dict)
+```
+
+teríamos um `dict` Python com:
+
+```Python
+{
+ 'username': 'john',
+ 'password': 'secret',
+ 'email': 'john.doe@example.com',
+ 'full_name': None,
+}
+```
+
+#### Desembrulhando um `dict`
+
+Se tomarmos um `dict` como `user_dict` e passarmos para uma função (ou classe) com `**user_dict`, o Python irá "desembrulhá-lo". Ele passará as chaves e valores do `user_dict` diretamente como argumentos chave-valor.
+
+Então, continuando com o `user_dict` acima, escrevendo:
+
+```Python
+UserInDB(**user_dict)
+```
+
+Resultaria em algo equivalente a:
+
+```Python
+UserInDB(
+ username="john",
+ password="secret",
+ email="john.doe@example.com",
+ full_name=None,
+)
+```
+
+Ou mais exatamente, usando `user_dict` diretamente, com qualquer conteúdo que ele possa ter no futuro:
+
+```Python
+UserInDB(
+ username = user_dict["username"],
+ password = user_dict["password"],
+ email = user_dict["email"],
+ full_name = user_dict["full_name"],
+)
+```
+
+#### Um modelo Pydantic a partir do conteúdo de outro
+
+Como no exemplo acima, obtivemos o `user_dict` a partir do `user_in.dict()`, este código:
+
+```Python
+user_dict = user_in.dict()
+UserInDB(**user_dict)
+```
+
+seria equivalente a:
+
+```Python
+UserInDB(**user_in.dict())
+```
+
+...porque `user_in.dict()` é um `dict`, e depois fazemos o Python "desembrulhá-lo" passando-o para UserInDB precedido por `**`.
+
+Então, obtemos um modelo Pydantic a partir dos dados em outro modelo Pydantic.
+
+#### Desembrulhando um `dict` e palavras-chave extras
+
+E, então, adicionando o argumento de palavra-chave extra `hashed_password=hashed_password`, como em:
+
+```Python
+UserInDB(**user_in.dict(), hashed_password=hashed_password)
+```
+
+...acaba sendo como:
+
+```Python
+UserInDB(
+ username = user_dict["username"],
+ password = user_dict["password"],
+ email = user_dict["email"],
+ full_name = user_dict["full_name"],
+ hashed_password = hashed_password,
+)
+```
+
+!!! warning
+ As funções adicionais de suporte são apenas para demonstração de um fluxo possível dos dados, mas é claro que elas não fornecem segurança real.
+
+## Reduzir duplicação
+
+Reduzir a duplicação de código é uma das ideias principais no **FastAPI**.
+
+A duplicação de código aumenta as chances de bugs, problemas de segurança, problemas de desincronização de código (quando você atualiza em um lugar, mas não em outros), etc.
+
+E esses modelos estão compartilhando muitos dos dados e duplicando nomes e tipos de atributos.
+
+Nós poderíamos fazer melhor.
+
+Podemos declarar um modelo `UserBase` que serve como base para nossos outros modelos. E então podemos fazer subclasses desse modelo que herdam seus atributos (declarações de tipo, validação, etc.).
+
+Toda conversão de dados, validação, documentação, etc. ainda funcionará normalmente.
+
+Dessa forma, podemos declarar apenas as diferenças entre os modelos (com `password` em texto claro, com `hashed_password` e sem senha):
+
+=== "Python 3.6 and above"
+
+ ```Python hl_lines="9 15-16 19-20 23-24"
+ {!> ../../../docs_src/extra_models/tutorial002.py!}
+ ```
+
+=== "Python 3.10 and above"
+
+ ```Python hl_lines="7 13-14 17-18 21-22"
+ {!> ../../../docs_src/extra_models/tutorial002_py310.py!}
+ ```
+
+## `Union` ou `anyOf`
+
+Você pode declarar uma resposta como o `Union` de dois tipos, o que significa que a resposta seria qualquer um dos dois.
+
+Isso será definido no OpenAPI com `anyOf`.
+
+Para fazer isso, use a dica de tipo padrão do Python `typing.Union`:
+
+!!! note
+ Ao definir um `Union`, inclua o tipo mais específico primeiro, seguido pelo tipo menos específico. No exemplo abaixo, o tipo mais específico `PlaneItem` vem antes de `CarItem` em `Union[PlaneItem, CarItem]`.
+
+=== "Python 3.6 and above"
+
+ ```Python hl_lines="1 14-15 18-20 33"
+ {!> ../../../docs_src/extra_models/tutorial003.py!}
+ ```
+
+=== "Python 3.10 and above"
+
+ ```Python hl_lines="1 14-15 18-20 33"
+ {!> ../../../docs_src/extra_models/tutorial003_py310.py!}
+ ```
+
+### `Union` no Python 3.10
+
+Neste exemplo, passamos `Union[PlaneItem, CarItem]` como o valor do argumento `response_model`.
+
+Dado que estamos passando-o como um **valor para um argumento** em vez de colocá-lo em uma **anotação de tipo**, precisamos usar `Union` mesmo no Python 3.10.
+
+Se estivesse em uma anotação de tipo, poderíamos ter usado a barra vertical, como:
+
+```Python
+some_variable: PlaneItem | CarItem
+```
+
+Mas se colocarmos isso em `response_model=PlaneItem | CarItem` teríamos um erro, pois o Python tentaria executar uma **operação inválida** entre `PlaneItem` e `CarItem` em vez de interpretar isso como uma anotação de tipo.
+
+## Lista de modelos
+
+Da mesma forma, você pode declarar respostas de listas de objetos.
+
+Para isso, use o padrão Python `typing.List` (ou simplesmente `list` no Python 3.9 e superior):
+
+=== "Python 3.6 and above"
+
+ ```Python hl_lines="1 20"
+ {!> ../../../docs_src/extra_models/tutorial004.py!}
+ ```
+
+=== "Python 3.9 and above"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/extra_models/tutorial004_py39.py!}
+ ```
+
+## Resposta com `dict` arbitrário
+
+Você também pode declarar uma resposta usando um simples `dict` arbitrário, declarando apenas o tipo das chaves e valores, sem usar um modelo Pydantic.
+
+Isso é útil se você não souber os nomes de campo / atributo válidos (que seriam necessários para um modelo Pydantic) antecipadamente.
+
+Neste caso, você pode usar `typing.Dict` (ou simplesmente dict no Python 3.9 e superior):
+
+=== "Python 3.6 and above"
+
+ ```Python hl_lines="1 8"
+ {!> ../../../docs_src/extra_models/tutorial005.py!}
+ ```
+
+=== "Python 3.9 and above"
+
+ ```Python hl_lines="6"
+ {!> ../../../docs_src/extra_models/tutorial005_py39.py!}
+ ```
+
+## Em resumo
+
+Use vários modelos Pydantic e herde livremente para cada caso.
+
+Não é necessário ter um único modelo de dados por entidade se essa entidade precisar ter diferentes "estados". No caso da "entidade" de usuário com um estado que inclui `password`, `password_hash` e sem senha.
diff --git a/docs/pt/docs/tutorial/header-params.md b/docs/pt/docs/tutorial/header-params.md
index 94ee784cd..bc8843327 100644
--- a/docs/pt/docs/tutorial/header-params.md
+++ b/docs/pt/docs/tutorial/header-params.md
@@ -6,36 +6,36 @@ Você pode definir parâmetros de Cabeçalho da mesma maneira que define paramê
Primeiro importe `Header`:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="3"
- {!> ../../../docs_src/header_params/tutorial001.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="1"
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/header_params/tutorial001.py!}
+ ```
+
## Declare parâmetros de `Header`
Então declare os paramêtros de cabeçalho usando a mesma estrutura que em `Path`, `Query` e `Cookie`.
O primeiro valor é o valor padrão, você pode passar todas as validações adicionais ou parâmetros de anotação:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="9"
- {!> ../../../docs_src/header_params/tutorial001.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial001.py!}
+ ```
+
!!! note "Detalhes Técnicos"
`Header` é uma classe "irmã" de `Path`, `Query` e `Cookie`. Ela também herda da mesma classe em comum `Param`.
@@ -60,18 +60,18 @@ Portanto, você pode usar `user_agent` como faria normalmente no código Python,
Se por algum motivo você precisar desabilitar a conversão automática de sublinhados para hífens, defina o parâmetro `convert_underscores` de `Header` para `False`:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="10"
- {!> ../../../docs_src/header_params/tutorial002.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="8"
{!> ../../../docs_src/header_params/tutorial002_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/header_params/tutorial002.py!}
+ ```
+
!!! warning "Aviso"
Antes de definir `convert_underscores` como `False`, lembre-se de que alguns proxies e servidores HTTP não permitem o uso de cabeçalhos com sublinhados.
@@ -85,22 +85,22 @@ Você receberá todos os valores do cabeçalho duplicado como uma `list` Python.
Por exemplo, para declarar um cabeçalho de `X-Token` que pode aparecer mais de uma vez, você pode escrever:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
- ```Python hl_lines="9"
- {!> ../../../docs_src/header_params/tutorial003.py!}
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/header_params/tutorial003_py310.py!}
```
-=== "Python 3.9 and above"
+=== "Python 3.9+"
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial003_py39.py!}
```
-=== "Python 3.10 and above"
+=== "Python 3.6+"
- ```Python hl_lines="7"
- {!> ../../../docs_src/header_params/tutorial003_py310.py!}
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial003.py!}
```
Se você se comunicar com essa *operação de caminho* enviando dois cabeçalhos HTTP como:
diff --git a/docs/pt/docs/tutorial/path-operation-configuration.md b/docs/pt/docs/tutorial/path-operation-configuration.md
new file mode 100644
index 000000000..e0a23f665
--- /dev/null
+++ b/docs/pt/docs/tutorial/path-operation-configuration.md
@@ -0,0 +1,180 @@
+# Configuração da Operação de Rota
+
+Existem vários parâmetros que você pode passar para o seu *decorador de operação de rota* para configurá-lo.
+
+!!! warning "Aviso"
+ Observe que esses parâmetros são passados diretamente para o *decorador de operação de rota*, não para a sua *função de operação de rota*.
+
+## Código de Status da Resposta
+
+Você pode definir o `status_code` (HTTP) para ser usado na resposta da sua *operação de rota*.
+
+Você pode passar diretamente o código `int`, como `404`.
+
+Mas se você não se lembrar o que cada código numérico significa, pode usar as constantes de atalho em `status`:
+
+=== "Python 3.6 and above"
+
+ ```Python hl_lines="3 17"
+ {!> ../../../docs_src/path_operation_configuration/tutorial001.py!}
+ ```
+
+=== "Python 3.9 and above"
+
+ ```Python hl_lines="3 17"
+ {!> ../../../docs_src/path_operation_configuration/tutorial001_py39.py!}
+ ```
+
+=== "Python 3.10 and above"
+
+ ```Python hl_lines="1 15"
+ {!> ../../../docs_src/path_operation_configuration/tutorial001_py310.py!}
+ ```
+
+Esse código de status será usado na resposta e será adicionado ao esquema OpenAPI.
+
+!!! note "Detalhes Técnicos"
+ Você também poderia usar `from starlette import status`.
+
+ **FastAPI** fornece o mesmo `starlette.status` como `fastapi.status` apenas como uma conveniência para você, o desenvolvedor. Mas vem diretamente do Starlette.
+
+## Tags
+
+Você pode adicionar tags para sua *operação de rota*, passe o parâmetro `tags` com uma `list` de `str` (comumente apenas um `str`):
+
+=== "Python 3.6 and above"
+
+ ```Python hl_lines="17 22 27"
+ {!> ../../../docs_src/path_operation_configuration/tutorial002.py!}
+ ```
+
+=== "Python 3.9 and above"
+
+ ```Python hl_lines="17 22 27"
+ {!> ../../../docs_src/path_operation_configuration/tutorial002_py39.py!}
+ ```
+
+=== "Python 3.10 and above"
+
+ ```Python hl_lines="15 20 25"
+ {!> ../../../docs_src/path_operation_configuration/tutorial002_py310.py!}
+ ```
+
+Eles serão adicionados ao esquema OpenAPI e usados pelas interfaces de documentação automática:
+
+
+
+### Tags com Enums
+
+Se você tem uma grande aplicação, você pode acabar acumulando **várias tags**, e você gostaria de ter certeza de que você sempre usa a **mesma tag** para *operações de rota* relacionadas.
+
+Nestes casos, pode fazer sentido armazenar as tags em um `Enum`.
+
+**FastAPI** suporta isso da mesma maneira que com strings simples:
+
+```Python hl_lines="1 8-10 13 18"
+{!../../../docs_src/path_operation_configuration/tutorial002b.py!}
+```
+
+## Resumo e descrição
+
+Você pode adicionar um `summary` e uma `description`:
+
+=== "Python 3.6 and above"
+
+ ```Python hl_lines="20-21"
+ {!> ../../../docs_src/path_operation_configuration/tutorial003.py!}
+ ```
+
+=== "Python 3.9 and above"
+
+ ```Python hl_lines="20-21"
+ {!> ../../../docs_src/path_operation_configuration/tutorial003_py39.py!}
+ ```
+
+=== "Python 3.10 and above"
+
+ ```Python hl_lines="18-19"
+ {!> ../../../docs_src/path_operation_configuration/tutorial003_py310.py!}
+ ```
+
+## Descrição do docstring
+
+Como as descrições tendem a ser longas e cobrir várias linhas, você pode declarar a descrição da *operação de rota* na docstring da função e o **FastAPI** irá lê-la de lá.
+
+Você pode escrever Markdown na docstring, ele será interpretado e exibido corretamente (levando em conta a indentação da docstring).
+
+=== "Python 3.6 and above"
+
+ ```Python hl_lines="19-27"
+ {!> ../../../docs_src/path_operation_configuration/tutorial004.py!}
+ ```
+
+=== "Python 3.9 and above"
+
+ ```Python hl_lines="19-27"
+ {!> ../../../docs_src/path_operation_configuration/tutorial004_py39.py!}
+ ```
+
+=== "Python 3.10 and above"
+
+ ```Python hl_lines="17-25"
+ {!> ../../../docs_src/path_operation_configuration/tutorial004_py310.py!}
+ ```
+
+Ela será usada nas documentações interativas:
+
+
+
+
+## Descrição da resposta
+
+Você pode especificar a descrição da resposta com o parâmetro `response_description`:
+
+=== "Python 3.6 and above"
+
+ ```Python hl_lines="21"
+ {!> ../../../docs_src/path_operation_configuration/tutorial005.py!}
+ ```
+
+=== "Python 3.9 and above"
+
+ ```Python hl_lines="21"
+ {!> ../../../docs_src/path_operation_configuration/tutorial005_py39.py!}
+ ```
+
+=== "Python 3.10 and above"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/path_operation_configuration/tutorial005_py310.py!}
+ ```
+
+!!! info "Informação"
+ Note que `response_description` se refere especificamente à resposta, a `description` se refere à *operação de rota* em geral.
+
+!!! check
+ OpenAPI especifica que cada *operação de rota* requer uma descrição de resposta.
+
+ Então, se você não fornecer uma, o **FastAPI** irá gerar automaticamente uma de "Resposta bem-sucedida".
+
+
+
+## Depreciar uma *operação de rota*
+
+Se você precisar marcar uma *operação de rota* como descontinuada, mas sem removê-la, passe o parâmetro `deprecated`:
+
+```Python hl_lines="16"
+{!../../../docs_src/path_operation_configuration/tutorial006.py!}
+```
+
+Ela será claramente marcada como descontinuada nas documentações interativas:
+
+
+
+Verifique como *operações de rota* descontinuadas e não descontinuadas se parecem:
+
+
+
+## Resumindo
+
+Você pode configurar e adicionar metadados para suas *operações de rota* facilmente passando parâmetros para os *decoradores de operação de rota*.
diff --git a/docs/pt/docs/tutorial/path-params-numeric-validations.md b/docs/pt/docs/tutorial/path-params-numeric-validations.md
index f478fd190..ec9b74b30 100644
--- a/docs/pt/docs/tutorial/path-params-numeric-validations.md
+++ b/docs/pt/docs/tutorial/path-params-numeric-validations.md
@@ -6,36 +6,36 @@ Do mesmo modo que você pode declarar mais validações e metadados para parâme
Primeiro, importe `Path` de `fastapi`:
-=== "Python 3.6 e superiores"
-
- ```Python hl_lines="3"
- {!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
- ```
-
-=== "Python 3.10 e superiores"
+=== "Python 3.10+"
```Python hl_lines="1"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
+ ```
+
## Declare metadados
Você pode declarar todos os parâmetros da mesma maneira que na `Query`.
Por exemplo para declarar um valor de metadado `title` para o parâmetro de rota `item_id` você pode digitar:
-=== "Python 3.6 e superiores"
-
- ```Python hl_lines="10"
- {!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
- ```
-
-=== "Python 3.10 e superiores"
+=== "Python 3.10+"
```Python hl_lines="8"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
+ ```
+
!!! note "Nota"
Um parâmetro de rota é sempre obrigatório, como se fizesse parte da rota.
diff --git a/docs/pt/docs/tutorial/query-params.md b/docs/pt/docs/tutorial/query-params.md
index 189724396..3ada4fd21 100644
--- a/docs/pt/docs/tutorial/query-params.md
+++ b/docs/pt/docs/tutorial/query-params.md
@@ -63,18 +63,18 @@ Os valores dos parâmetros na sua função serão:
Da mesma forma, você pode declarar parâmetros de consulta opcionais, definindo o valor padrão para `None`:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="9"
- {!> ../../../docs_src/query_params/tutorial002.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/query_params/tutorial002_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params/tutorial002.py!}
+ ```
+
Nesse caso, o parâmetro da função `q` será opcional, e `None` será o padrão.
!!! check "Verificar"
@@ -85,18 +85,18 @@ Nesse caso, o parâmetro da função `q` será opcional, e `None` será o padrã
Você também pode declarar tipos `bool`, e eles serão convertidos:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="9"
- {!> ../../../docs_src/query_params/tutorial003.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/query_params/tutorial003_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params/tutorial003.py!}
+ ```
+
Nesse caso, se você for para:
```
@@ -137,18 +137,18 @@ E você não precisa declarar eles em nenhuma ordem específica.
Eles serão detectados pelo nome:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="8 10"
- {!> ../../../docs_src/query_params/tutorial004.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="6 8"
{!> ../../../docs_src/query_params/tutorial004_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="8 10"
+ {!> ../../../docs_src/query_params/tutorial004.py!}
+ ```
+
## Parâmetros de consulta obrigatórios
Quando você declara um valor padrão para parâmetros que não são de rota (até agora, nós vimos apenas parâmetros de consulta), então eles não são obrigatórios.
@@ -203,17 +203,18 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
E claro, você pode definir alguns parâmetros como obrigatórios, alguns possuindo um valor padrão, e outros sendo totalmente opcionais:
-=== "Python 3.6 and above"
+=== "Python 3.10+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params/tutorial006_py310.py!}
+ ```
+
+=== "Python 3.6+"
```Python hl_lines="10"
{!> ../../../docs_src/query_params/tutorial006.py!}
```
-=== "Python 3.10 and above"
-
- ```Python hl_lines="8"
- {!> ../../../docs_src/query_params/tutorial006_py310.py!}
- ```
Nesse caso, existem 3 parâmetros de consulta:
* `needy`, um `str` obrigatório.
diff --git a/docs/pt/mkdocs.yml b/docs/pt/mkdocs.yml
index 2a8302715..f51c3ecc2 100644
--- a/docs/pt/mkdocs.yml
+++ b/docs/pt/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -70,9 +71,12 @@ nav:
- tutorial/body.md
- tutorial/body-multiple-params.md
- tutorial/body-fields.md
+ - tutorial/body-nested-models.md
- tutorial/extra-data-types.md
+ - tutorial/extra-models.md
- tutorial/query-params-str-validations.md
- tutorial/path-params-numeric-validations.md
+ - tutorial/path-operation-configuration.md
- tutorial/cookie-params.md
- tutorial/header-params.md
- tutorial/response-status-code.md
@@ -142,6 +146,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/ru/docs/alternatives.md b/docs/ru/docs/alternatives.md
new file mode 100644
index 000000000..9e3c497d1
--- /dev/null
+++ b/docs/ru/docs/alternatives.md
@@ -0,0 +1,460 @@
+# Альтернативы, источники вдохновения и сравнения
+
+Что вдохновило на создание **FastAPI**, сравнение его с альтернативами и чему он научился у них.
+
+## Введение
+
+**FastAPI** не существовал бы, если б не было более ранних работ других людей.
+
+Они создали большое количество инструментов, которые вдохновили меня на создание **FastAPI**.
+
+Я всячески избегал создания нового фреймворка в течение нескольких лет.
+Сначала я пытался собрать все нужные функции, которые ныне есть в **FastAPI**, используя множество различных фреймворков, плагинов и инструментов.
+
+Но в какой-то момент не осталось другого выбора, кроме как создать что-то, что предоставляло бы все эти функции сразу.
+Взять самые лучшие идеи из предыдущих инструментов и, используя новые возможности Python (которых не было до версии 3.6, то есть подсказки типов), объединить их.
+
+## Предшествующие инструменты
+
+### Django
+
+Это самый популярный Python-фреймворк, и он пользуется доверием.
+Он используется для создания проектов типа Instagram.
+
+Django довольно тесно связан с реляционными базами данных (такими как MySQL или PostgreSQL), потому использовать NoSQL базы данных (например, Couchbase, MongoDB, Cassandra и т.п.) в качестве основного хранилища данных - непросто.
+
+Он был создан для генерации HTML-страниц на сервере, а не для создания API, используемых современными веб-интерфейсами (React, Vue.js, Angular и т.п.) или другими системами (например, IoT) взаимодействующими с сервером.
+
+### Django REST Framework
+
+Фреймворк Django REST был создан, как гибкий инструментарий для создания веб-API на основе Django.
+
+DRF использовался многими компаниями, включая Mozilla, Red Hat и Eventbrite.
+
+Это был один из первых примеров **автоматического документирования API** и это была одна из первых идей, вдохновивших на создание **FastAPI**.
+
+!!! note "Заметка"
+ Django REST Framework был создан Tom Christie.
+ Он же создал Starlette и Uvicorn, на которых основан **FastAPI**.
+
+!!! check "Идея для **FastAPI**"
+ Должно быть автоматическое создание документации API с пользовательским веб-интерфейсом.
+
+### Flask
+
+Flask - это "микрофреймворк", в нём нет интеграции с базами данных и многих других вещей, которые предустановлены в Django.
+
+Его простота и гибкость дают широкие возможности, такие как использование баз данных NoSQL в качестве основной системы хранения данных.
+
+Он очень прост, его изучение интуитивно понятно, хотя в некоторых местах документация довольно техническая.
+
+Flask часто используется и для приложений, которым не нужна база данных, настройки прав доступа для пользователей и прочие из множества функций, предварительно встроенных в Django.
+Хотя многие из этих функций могут быть добавлены с помощью плагинов.
+
+Такое разделение на части и то, что это "микрофреймворк", который можно расширить, добавляя необходимые возможности, было ключевой особенностью, которую я хотел сохранить.
+
+Простота Flask, показалась мне подходящей для создания API.
+Но ещё нужно было найти "Django REST Framework" для Flask.
+
+!!! check "Идеи для **FastAPI**"
+ Это будет микрофреймворк. К нему легко будет добавить необходимые инструменты и части.
+
+ Должна быть простая и лёгкая в использовании система маршрутизации запросов.
+
+
+### Requests
+
+На самом деле **FastAPI** не является альтернативой **Requests**.
+Их область применения очень разная.
+
+В принципе, можно использовать Requests *внутри* приложения FastAPI.
+
+Но всё же я использовал в FastAPI некоторые идеи из Requests.
+
+**Requests** - это библиотека для взаимодействия с API в качестве клиента,
+в то время как **FastAPI** - это библиотека для *создания* API (то есть сервера).
+
+Они, так или иначе, диаметрально противоположны и дополняют друг друга.
+
+Requests имеет очень простой и понятный дизайн, очень прост в использовании и имеет разумные значения по умолчанию.
+И в то же время он очень мощный и настраиваемый.
+
+Вот почему на официальном сайте написано:
+
+> Requests - один из самых загружаемых пакетов Python всех времен
+
+
+Использовать его очень просто. Например, чтобы выполнить запрос `GET`, Вы бы написали:
+
+```Python
+response = requests.get("http://example.com/some/url")
+```
+
+Противоположная *операция пути* в FastAPI может выглядеть следующим образом:
+
+```Python hl_lines="1"
+@app.get("/some/url")
+def read_url():
+ return {"message": "Hello World"}
+```
+
+Глядите, как похоже `requests.get(...)` и `@app.get(...)`.
+
+!!! check "Идеи для **FastAPI**"
+ * Должен быть простой и понятный API.
+ * Нужно использовать названия HTTP-методов (операций) для упрощения понимания происходящего.
+ * Должны быть разумные настройки по умолчанию и широкие возможности их кастомизации.
+
+
+### Swagger / OpenAPI
+
+Главной функцией, которую я хотел унаследовать от Django REST Framework, была автоматическая документация API.
+
+Но потом я обнаружил, что существует стандарт документирования API, использующий JSON (или YAML, расширение JSON) под названием Swagger.
+
+И к нему уже был создан пользовательский веб-интерфейс.
+Таким образом, возможность генерировать документацию Swagger для API позволила бы использовать этот интерфейс.
+
+В какой-то момент Swagger был передан Linux Foundation и переименован в OpenAPI.
+
+Вот почему, когда говорят о версии 2.0, обычно говорят "Swagger", а для версии 3+ "OpenAPI".
+
+!!! check "Идеи для **FastAPI**"
+ Использовать открытые стандарты для спецификаций API вместо самодельных схем.
+
+ Совместимость с основанными на стандартах пользовательскими интерфейсами:
+
+ * Swagger UI
+ * ReDoc
+
+ Они были выбраны за популярность и стабильность.
+ Но сделав беглый поиск, Вы можете найти десятки альтернативных пользовательских интерфейсов для OpenAPI, которые Вы можете использовать с **FastAPI**.
+
+### REST фреймворки для Flask
+
+Существует несколько REST фреймворков для Flask, но потратив время и усилия на их изучение, я обнаружил, что многие из них не обновляются или заброшены и имеют нерешённые проблемы из-за которых они непригодны к использованию.
+
+### Marshmallow
+
+Одной из основных функций, необходимых системам API, является "сериализация" данных, то есть преобразование данных из кода (Python) во что-то, что может быть отправлено по сети.
+Например, превращение объекта содержащего данные из базы данных в объект JSON, конвертация объекта `datetime` в строку и т.п.
+
+Еще одна важная функция, необходимая API — проверка данных, позволяющая убедиться, что данные действительны и соответствуют заданным параметрам.
+Как пример, можно указать, что ожидаются данные типа `int`, а не какая-то произвольная строка.
+Это особенно полезно для входящих данных.
+
+Без системы проверки данных Вам пришлось бы прописывать все проверки вручную.
+
+Именно для обеспечения этих функций и была создана Marshmallow.
+Это отличная библиотека и я много раз пользовался ею раньше.
+
+Но она была создана до того, как появились подсказки типов Python.
+Итак, чтобы определить каждую схему,
+Вам нужно использовать определенные утилиты и классы, предоставляемые Marshmallow.
+
+!!! check "Идея для **FastAPI**"
+ Использовать код программы для автоматического создания "схем", определяющих типы данных и их проверку.
+
+### Webargs
+
+Другая немаловажная функция API - парсинг данных из входящих запросов.
+
+Webargs - это инструмент, который был создан для этого и поддерживает несколько фреймворков, включая Flask.
+
+Для проверки данных он использует Marshmallow и создан теми же авторами.
+
+Это превосходный инструмент и я тоже часто пользовался им до **FastAPI**.
+
+!!! info "Информация"
+ Webargs бы создан разработчиками Marshmallow.
+
+!!! check "Идея для **FastAPI**"
+ Должна быть автоматическая проверка входных данных.
+
+### APISpec
+
+Marshmallow и Webargs осуществляют проверку, анализ и сериализацию данных как плагины.
+
+Но документации API всё ещё не было. Тогда был создан APISpec.
+
+Это плагин для множества фреймворков, в том числе и для Starlette.
+
+Он работает так - Вы записываете определение схем, используя формат YAML, внутри докстринга каждой функции, обрабатывающей маршрут.
+
+Используя эти докстринги, он генерирует схему OpenAPI.
+
+Так это работает для Flask, Starlette, Responder и т.п.
+
+Но теперь у нас возникает новая проблема - наличие постороннего микро-синтаксиса внутри кода Python (большие YAML).
+
+Редактор кода не особо может помочь в такой парадигме.
+А изменив какие-то параметры или схемы для Marshmallow можно забыть отредактировать докстринг с YAML и сгенерированная схема становится недействительной.
+
+!!! info "Информация"
+ APISpec тоже был создан авторами Marshmallow.
+
+!!! check "Идея для **FastAPI**"
+ Необходима поддержка открытого стандарта для API - OpenAPI.
+
+### Flask-apispec
+
+Это плагин для Flask, который связан с Webargs, Marshmallow и APISpec.
+
+Он получает информацию от Webargs и Marshmallow, а затем использует APISpec для автоматического создания схемы OpenAPI.
+
+Это отличный, но крайне недооценённый инструмент.
+Он должен быть более популярен, чем многие плагины для Flask.
+Возможно, это связано с тем, что его документация слишком скудна и абстрактна.
+
+Он избавил от необходимости писать чужеродный синтаксис YAML внутри докстрингов.
+
+Такое сочетание Flask, Flask-apispec, Marshmallow и Webargs было моим любимым стеком при построении бэкенда до появления **FastAPI**.
+
+Использование этого стека привело к созданию нескольких генераторов проектов. Я и некоторые другие команды до сих пор используем их:
+
+* https://github.com/tiangolo/full-stack
+* https://github.com/tiangolo/full-stack-flask-couchbase
+* https://github.com/tiangolo/full-stack-flask-couchdb
+
+Эти генераторы проектов также стали основой для [Генераторов проектов с **FastAPI**](project-generation.md){.internal-link target=_blank}.
+
+!!! info "Информация"
+ Как ни странно, но Flask-apispec тоже создан авторами Marshmallow.
+
+!!! check "Идея для **FastAPI**"
+ Схема OpenAPI должна создаваться автоматически и использовать тот же код, который осуществляет сериализацию и проверку данных.
+
+### NestJS (и Angular)
+
+Здесь даже не используется Python. NestJS - этот фреймворк написанный на JavaScript (TypeScript), основанный на NodeJS и вдохновлённый Angular.
+
+Он позволяет получить нечто похожее на то, что можно сделать с помощью Flask-apispec.
+
+В него встроена система внедрения зависимостей, ещё одна идея взятая от Angular.
+Однако требуется предварительная регистрация "внедрений" (как и во всех других известных мне системах внедрения зависимостей), что увеличивает количество и повторяемость кода.
+
+Так как параметры в нём описываются с помощью типов TypeScript (аналогично подсказкам типов в Python), поддержка редактора работает довольно хорошо.
+
+Но поскольку данные из TypeScript не сохраняются после компиляции в JavaScript, он не может полагаться на подсказки типов для определения проверки данных, сериализации и документации.
+Из-за этого и некоторых дизайнерских решений, для валидации, сериализации и автоматической генерации схем, приходится во многих местах добавлять декораторы.
+Таким образом, это становится довольно многословным.
+
+Кроме того, он не очень хорошо справляется с вложенными моделями.
+Если в запросе имеется объект JSON, внутренние поля которого, в свою очередь, являются вложенными объектами JSON, это не может быть должным образом задокументировано и проверено.
+
+!!! check "Идеи для **FastAPI** "
+ Нужно использовать подсказки типов, чтоб воспользоваться поддержкой редактора кода.
+
+ Нужна мощная система внедрения зависимостей. Необходим способ для уменьшения повторов кода.
+
+### Sanic
+
+Sanic был одним из первых чрезвычайно быстрых Python-фреймворков основанных на `asyncio`.
+Он был сделан очень похожим на Flask.
+
+!!! note "Технические детали"
+ В нём использован `uvloop` вместо стандартного цикла событий `asyncio`, что и сделало его таким быстрым.
+
+ Он явно вдохновил создателей Uvicorn и Starlette, которые в настоящее время быстрее Sanic в открытых бенчмарках.
+
+!!! check "Идеи для **FastAPI**"
+ Должна быть сумасшедшая производительность.
+
+ Для этого **FastAPI** основан на Starlette, самом быстром из доступных фреймворков (по замерам незаинтересованных лиц).
+
+### Falcon
+
+Falcon - ещё один высокопроизводительный Python-фреймворк.
+В нём минимум функций и он создан, чтоб быть основой для других фреймворков, например, Hug.
+
+Функции в нём получают два параметра - "запрос к серверу" и "ответ сервера".
+Затем Вы "читаете" часть запроса и "пишите" часть ответа.
+Из-за такой конструкции невозможно объявить параметры запроса и тела сообщения со стандартными подсказками типов Python в качестве параметров функции.
+
+Таким образом, и валидацию данных, и их сериализацию, и документацию нужно прописывать вручную.
+Либо эти функции должны быть встроены во фреймворк, сконструированный поверх Falcon, как в Hug.
+Такая же особенность присутствует и в других фреймворках, вдохновлённых идеей Falcon, использовать только один объект запроса и один объект ответа.
+
+!!! check "Идея для **FastAPI**"
+ Найдите способы добиться отличной производительности.
+
+ Объявлять параметры `ответа сервера` в функциях, как в Hug.
+
+ Хотя в FastAPI это необязательно и используется в основном для установки заголовков, куки и альтернативных кодов состояния.
+
+### Molten
+
+Molten мне попался на начальной стадии написания **FastAPI**. В нём были похожие идеи:
+
+* Использование подсказок типов.
+* Валидация и документация исходя из этих подсказок.
+* Система внедрения зависимостей.
+
+В нём не используются сторонние библиотеки (такие, как Pydantic) для валидации, сериализации и документации.
+Поэтому переиспользовать эти определения типов непросто.
+
+Также требуется более подробная конфигурация и используется стандарт WSGI, который не предназначен для использования с высокопроизводительными инструментами, такими как Uvicorn, Starlette и Sanic, в отличие от ASGI.
+
+Его система внедрения зависимостей требует предварительной регистрации, и зависимости определяются, как объявления типов.
+Из-за этого невозможно объявить более одного "компонента" (зависимости), который предоставляет определенный тип.
+
+Маршруты объявляются в единственном месте с использованием функций, объявленных в других местах (вместо использования декораторов, в которые могут быть обёрнуты функции, обрабатывающие конкретные ресурсы).
+Это больше похоже на Django, чем на Flask и Starlette.
+Он разделяет в коде вещи, которые довольно тесно связаны.
+
+!!! check "Идея для **FastAPI**"
+ Определить дополнительные проверки типов данных, используя значения атрибутов модели "по умолчанию".
+ Это улучшает помощь редактора и раньше это не было доступно в Pydantic.
+
+ Фактически это подтолкнуло на обновление Pydantic для поддержки одинакового стиля проверок (теперь этот функционал уже доступен в Pydantic).
+
+### Hug
+
+Hug был одним из первых фреймворков, реализовавших объявление параметров API с использованием подсказок типов Python.
+Эта отличная идея была использована и другими инструментами.
+
+При объявлении параметров вместо стандартных типов Python использовались собственные типы, но всё же это был огромный шаг вперед.
+
+Это также был один из первых фреймворков, генерировавших полную API-схему в формате JSON.
+
+Данная схема не придерживалась стандартов вроде OpenAPI и JSON Schema.
+Поэтому было бы непросто совместить её с другими инструментами, такими как Swagger UI.
+Но опять же, это была очень инновационная идея.
+
+Ещё у него есть интересная и необычная функция: используя один и тот же фреймворк можно создавать и API, и CLI.
+
+Поскольку он основан на WSGI, старом стандарте для синхронных веб-фреймворков, он не может работать с веб-сокетами и другими модными штуками, но всё равно обладает высокой производительностью.
+
+!!! info "Информация"
+ Hug создан Timothy Crosley, автором `isort`, отличного инструмента для автоматической сортировки импортов в Python-файлах.
+
+!!! check "Идеи для **FastAPI**"
+ Hug повлиял на создание некоторых частей APIStar и был одним из инструментов, которые я счел наиболее многообещающими, наряду с APIStar.
+
+ Hug натолкнул на мысли использовать в **FastAPI** подсказки типов Python для автоматического создания схемы, определяющей API и его параметры.
+
+ Hug вдохновил **FastAPI** объявить параметр `ответа` в функциях для установки заголовков и куки.
+
+### APIStar (<= 0.5)
+
+Непосредственно перед тем, как принять решение о создании **FastAPI**, я обнаружил **APIStar**.
+В нем было почти все, что я искал и у него был отличный дизайн.
+
+Это была одна из первых реализаций фреймворка, использующего подсказки типов для объявления параметров и запросов, которые я когда-либо видел (до NestJS и Molten).
+Я нашёл его примерно в то же время, что и Hug, но APIStar использовал стандарт OpenAPI.
+
+В нём были автоматические проверка и сериализация данных и генерация схемы OpenAPI основанные на подсказках типов в нескольких местах.
+
+При определении схемы тела сообщения не использовались подсказки типов, как в Pydantic, это больше похоже на Marshmallow, поэтому помощь редактора была недостаточно хорошей, но всё же APIStar был лучшим доступным вариантом.
+
+На тот момент у него были лучшие показатели производительности (проигрывающие только Starlette).
+
+Изначально у него не было автоматической документации API для веб-интерфейса, но я знал, что могу добавить к нему Swagger UI.
+
+В APIStar была система внедрения зависимостей, которая тоже требовала предварительную регистрацию компонентов, как и ранее описанные инструменты.
+Но, тем не менее, это была отличная штука.
+
+Я не смог использовать его в полноценном проекте, так как были проблемы со встраиванием функций безопасности в схему OpenAPI, из-за которых невозможно было встроить все функции, применяемые в генераторах проектов на основе Flask-apispec.
+Я добавил в свой список задач создание пул-реквеста, добавляющего эту функциональность.
+
+В дальнейшем фокус проекта сместился.
+
+Это больше не был API-фреймворк, так как автор сосредоточился на Starlette.
+
+Ныне APIStar - это набор инструментов для проверки спецификаций OpenAPI.
+
+!!! info "Информация"
+ APIStar был создан Tom Christie. Тот самый парень, который создал:
+
+ * Django REST Framework
+ * Starlette (на котором основан **FastAPI**)
+ * Uvicorn (используемый в Starlette и **FastAPI**)
+
+!!! check "Идеи для **FastAPI**"
+ Воплощение.
+
+ Мне казалось блестящей идеей объявлять множество функций (проверка данных, сериализация, документация) с помощью одних и тех же типов Python, которые при этом обеспечивают ещё и помощь редактора кода.
+
+ После долгих поисков среди похожих друг на друга фреймворков и сравнения их различий, APIStar стал самым лучшим выбором.
+
+ Но APIStar перестал быть фреймворком для создания веб-сервера, зато появился Starlette, новая и лучшая основа для построения подобных систем.
+ Это была последняя капля, сподвигнувшая на создание **FastAPI**.
+
+ Я считаю **FastAPI** "духовным преемником" APIStar, улучившим его возможности благодаря урокам, извлечённым из всех упомянутых выше инструментов.
+
+## Что используется в **FastAPI**
+
+### Pydantic
+
+Pydantic - это библиотека для валидации данных, сериализации и документирования (используя JSON Schema), основываясь на подсказках типов Python, что делает его чрезвычайно интуитивным.
+
+Его можно сравнить с Marshmallow, хотя в бенчмарках Pydantic быстрее, чем Marshmallow.
+И он основан на тех же подсказках типов, которые отлично поддерживаются редакторами кода.
+
+!!! check "**FastAPI** использует Pydantic"
+ Для проверки данных, сериализации данных и автоматической документации моделей (на основе JSON Schema).
+
+ Затем **FastAPI** берёт эти схемы JSON и помещает их в схему OpenAPI, не касаясь других вещей, которые он делает.
+
+### Starlette
+
+Starlette - это легковесный ASGI фреймворк/набор инструментов, который идеален для построения высокопроизводительных асинхронных сервисов.
+
+Starlette очень простой и интуитивный.
+Он разработан таким образом, чтобы быть легко расширяемым и иметь модульные компоненты.
+
+В нём есть:
+
+* Впечатляющая производительность.
+* Поддержка веб-сокетов.
+* Фоновые задачи.
+* Обработка событий при старте и финише приложения.
+* Тестовый клиент на основе HTTPX.
+* Поддержка CORS, сжатие GZip, статические файлы, потоковая передача данных.
+* Поддержка сессий и куки.
+* 100% покрытие тестами.
+* 100% аннотированный код.
+* Несколько жёстких зависимостей.
+
+В настоящее время Starlette показывает самую высокую скорость среди Python-фреймворков в тестовых замерах.
+Быстрее только Uvicorn, который является сервером, а не фреймворком.
+
+Starlette обеспечивает весь функционал микрофреймворка, но не предоставляет автоматическую валидацию данных, сериализацию и документацию.
+
+**FastAPI** добавляет эти функции используя подсказки типов Python и Pydantic.
+Ещё **FastAPI** добавляет систему внедрения зависимостей, утилиты безопасности, генерацию схемы OpenAPI и т.д.
+
+!!! note "Технические детали"
+ ASGI - это новый "стандарт" разработанный участниками команды Django.
+ Он пока что не является "стандартом в Python" (то есть принятым PEP), но процесс принятия запущен.
+
+ Тем не менее он уже используется в качестве "стандарта" несколькими инструментами.
+ Это значительно улучшает совместимость, поскольку Вы можете переключиться с Uvicorn на любой другой ASGI-сервер (например, Daphne или Hypercorn) или Вы можете добавить ASGI-совместимые инструменты, такие как `python-socketio`.
+
+!!! check "**FastAPI** использует Starlette"
+ В качестве ядра веб-сервиса для обработки запросов, добавив некоторые функции сверху.
+
+ Класс `FastAPI` наследуется напрямую от класса `Starlette`.
+
+ Таким образом, всё что Вы могли делать со Starlette, Вы можете делать с **FastAPI**, по сути это прокачанный Starlette.
+
+### Uvicorn
+
+Uvicorn - это молниеносный ASGI-сервер, построенный на uvloop и httptools.
+
+Uvicorn является сервером, а не фреймворком.
+Например, он не предоставляет инструментов для маршрутизации запросов по ресурсам.
+Для этого нужна надстройка, такая как Starlette (или **FastAPI**).
+
+Он рекомендуется в качестве сервера для Starlette и **FastAPI**.
+
+!!! check "**FastAPI** рекомендует его"
+ Как основной сервер для запуска приложения **FastAPI**.
+
+ Вы можете объединить его с Gunicorn, чтобы иметь асинхронный многопроцессный сервер.
+
+ Узнать больше деталей можно в разделе [Развёртывание](deployment/index.md){.internal-link target=_blank}.
+
+## Тестовые замеры и скорость
+
+Чтобы понять, сравнить и увидеть разницу между Uvicorn, Starlette и FastAPI, ознакомьтесь с разделом [Тестовые замеры](benchmarks.md){.internal-link target=_blank}.
diff --git a/docs/ru/docs/benchmarks.md b/docs/ru/docs/benchmarks.md
new file mode 100644
index 000000000..259dca8e6
--- /dev/null
+++ b/docs/ru/docs/benchmarks.md
@@ -0,0 +1,37 @@
+# Замеры производительности
+
+Независимые тесты производительности приложений от TechEmpower показывают, что **FastAPI** под управлением Uvicorn один из самых быстрых Python-фреймворков и уступает только Starlette и Uvicorn (которые используются в FastAPI). (*)
+
+Но при просмотре и сравнении замеров производительности следует иметь в виду нижеописанное.
+
+## Замеры производительности и скорости
+
+В подобных тестах часто можно увидеть, что инструменты разного типа сравнивают друг с другом, как аналогичные.
+
+В частности, сравнивают вместе Uvicorn, Starlette и FastAPI (среди многих других инструментов).
+
+Чем проще проблема, которую решает инструмент, тем выше его производительность. И большинство тестов не проверяют дополнительные функции, предоставляемые инструментом.
+
+Иерархия инструментов имеет следующий вид:
+
+* **Uvicorn**: ASGI-сервер
+ * **Starlette** (использует Uvicorn): веб-микрофреймворк
+ * **FastAPI** (использует Starlette): API-микрофреймворк с дополнительными функциями для создания API, с валидацией данных и т.д.
+
+* **Uvicorn**:
+ * Будет иметь наилучшую производительность, так как не имеет большого количества дополнительного кода, кроме самого сервера.
+ * Вы не будете писать приложение на Uvicorn напрямую. Это означало бы, что Ваш код должен включать как минимум весь
+ код, предоставляемый Starlette (или **FastAPI**). И если Вы так сделаете, то в конечном итоге Ваше приложение будет иметь те же накладные расходы, что и при использовании фреймворка, минимизирующего код Вашего приложения и Ваши ошибки.
+ * Uvicorn подлежит сравнению с Daphne, Hypercorn, uWSGI и другими веб-серверами.
+
+* **Starlette**:
+ * Будет уступать Uvicorn по производительности. Фактически Starlette управляется Uvicorn и из-за выполнения большего количества кода он не может быть быстрее, чем Uvicorn.
+ * Зато он предоставляет Вам инструменты для создания простых веб-приложений с обработкой маршрутов URL и т.д.
+ * Starlette следует сравнивать с Sanic, Flask, Django и другими веб-фреймворками (или микрофреймворками).
+
+* **FastAPI**:
+ * Так же как Starlette использует Uvicorn и не может быть быстрее него, **FastAPI** использует Starlette, то есть он не может быть быстрее Starlette.
+ * FastAPI предоставляет больше возможностей поверх Starlette, которые наверняка Вам понадобятся при создании API, такие как проверка данных и сериализация. В довесок Вы ещё и получаете автоматическую документацию (автоматическая документация даже не увеличивает накладные расходы при работе приложения, так как она создается при запуске).
+ * Если Вы не используете FastAPI, а используете Starlette напрямую (или другой инструмент вроде Sanic, Flask, Responder и т.д.), Вам пришлось бы самостоятельно реализовать валидацию и сериализацию данных. То есть, в итоге, Ваше приложение имело бы такие же накладные расходы, как если бы оно было создано с использованием FastAPI. И во многих случаях валидация и сериализация данных представляют собой самый большой объём кода, написанного в приложениях.
+ * Таким образом, используя FastAPI Вы потратите меньше времени на разработку, уменьшите количество ошибок, строк кода и, вероятно, получите ту же производительность (или лучше), как и если бы не использовали его (поскольку Вам пришлось бы реализовать все его возможности в своем коде).
+ * FastAPI должно сравнивать с фреймворками веб-приложений (или наборами инструментов), которые обеспечивают валидацию и сериализацию данных, а также предоставляют автоматическую документацию, такими как Flask-apispec, NestJS, Molten и им подобные.
diff --git a/docs/ru/docs/contributing.md b/docs/ru/docs/contributing.md
index cb460beb0..f61ef1cb6 100644
--- a/docs/ru/docs/contributing.md
+++ b/docs/ru/docs/contributing.md
@@ -82,7 +82,7 @@ $ python -m venv env
-Ели в терминале появится ответ, что бинарник `pip` расположен по пути `.../env/bin/pip`, значит всё в порядке. 🎉
+Если в терминале появится ответ, что бинарник `pip` расположен по пути `.../env/bin/pip`, значит всё в порядке. 🎉
Во избежание ошибок в дальнейших шагах, удостоверьтесь, что в Вашем виртуальном окружении установлена последняя версия `pip`:
diff --git a/docs/ru/docs/project-generation.md b/docs/ru/docs/project-generation.md
new file mode 100644
index 000000000..76253d6f2
--- /dev/null
+++ b/docs/ru/docs/project-generation.md
@@ -0,0 +1,84 @@
+# Генераторы проектов - Шаблоны
+
+Чтобы начать работу быстрее, Вы можете использовать "генераторы проектов", в которые включены множество начальных настроек для функций безопасности, баз данных и некоторые эндпоинты API.
+
+В генераторе проектов всегда будут предустановлены какие-то настройки, которые Вам следует обновить и подогнать под свои нужды, но это может быть хорошей отправной точкой для Вашего проекта.
+
+## Full Stack FastAPI PostgreSQL
+
+GitHub: https://github.com/tiangolo/full-stack-fastapi-postgresql
+
+### Full Stack FastAPI PostgreSQL - Особенности
+
+* Полностью интегрирован с **Docker** (основан на Docker).
+* Развёртывается в режиме Docker Swarm.
+* Интегрирован с **Docker Compose** и оптимизирован для локальной разработки.
+* **Готовый к реальной работе** веб-сервер Python использующий Uvicorn и Gunicorn.
+* Бэкенд построен на фреймворке **FastAPI**:
+ * **Быстрый**: Высокопроизводительный, на уровне **NodeJS** и **Go** (благодаря Starlette и Pydantic).
+ * **Интуитивно понятный**: Отличная поддержка редактора. Автодополнение кода везде. Меньше времени на отладку.
+ * **Простой**: Разработан так, чтоб быть простым в использовании и изучении. Меньше времени на чтение документации.
+ * **Лаконичный**: Минимизировано повторение кода. Каждый объявленный параметр определяет несколько функций.
+ * **Надёжный**: Получите готовый к работе код. С автоматической интерактивной документацией.
+ * **Стандартизированный**: Основан на открытых стандартах API (OpenAPI и JSON Schema) и полностью совместим с ними.
+ * **Множество других возможностей** включая автоматическую проверку и сериализацию данных, интерактивную документацию, аутентификацию с помощью OAuth2 JWT-токенов и т.д.
+* **Безопасное хранение паролей**, которые хэшируются по умолчанию.
+* Аутентификация посредством **JWT-токенов**.
+* Модели **SQLAlchemy** (независящие от расширений Flask, а значит могут быть непосредственно использованы процессами Celery).
+* Базовая модель пользователя (измените или удалите её по необходимости).
+* **Alembic** для организации миграций.
+* **CORS** (Совместное использование ресурсов из разных источников).
+* **Celery**, процессы которого могут выборочно импортировать и использовать модели и код из остальной части бэкенда.
+* Тесты, на основе **Pytest**, интегрированные в Docker, чтобы Вы могли полностью проверить Ваше API, независимо от базы данных. Так как тесты запускаются в Docker, для них может создаваться новое хранилище данных каждый раз (Вы можете, по своему желанию, использовать ElasticSearch, MongoDB, CouchDB или другую СУБД, только лишь для проверки - будет ли Ваше API работать с этим хранилищем).
+* Простая интеграция Python с **Jupyter Kernels** для разработки удалённо или в Docker с расширениями похожими на Atom Hydrogen или Visual Studio Code Jupyter.
+* Фронтенд построен на фреймворке **Vue**:
+ * Сгенерирован с помощью Vue CLI.
+ * Поддерживает **аутентификацию с помощью JWT-токенов**.
+ * Страница логина.
+ * Перенаправление на страницу главной панели мониторинга после логина.
+ * Главная страница мониторинга с возможностью создания и изменения пользователей.
+ * Пользователь может изменять свои данные.
+ * **Vuex**.
+ * **Vue-router**.
+ * **Vuetify** для конструирования красивых компонентов страниц.
+ * **TypeScript**.
+ * Сервер Docker основан на **Nginx** (настроен для удобной работы с Vue-router).
+ * Многоступенчатая сборка Docker, то есть Вам не нужно сохранять или коммитить скомпилированный код.
+ * Тесты фронтенда запускаются во время сборки (можно отключить).
+ * Сделан настолько модульно, насколько возможно, поэтому работает "из коробки", но Вы можете повторно сгенерировать фронтенд с помощью Vue CLI или создать то, что Вам нужно и повторно использовать то, что захотите.
+* **PGAdmin** для СУБД PostgreSQL, которые легко можно заменить на PHPMyAdmin и MySQL.
+* **Flower** для отслеживания работы Celery.
+* Балансировка нагрузки между фронтендом и бэкендом с помощью **Traefik**, а значит, Вы можете расположить их на одном домене, разделив url-пути, так как они обслуживаются разными контейнерами.
+* Интеграция с Traefik включает автоматическую генерацию сертификатов Let's Encrypt для поддержки протокола **HTTPS**.
+* GitLab **CI** (непрерывная интеграция), которая включает тестирование фронтенда и бэкенда.
+
+## Full Stack FastAPI Couchbase
+
+GitHub: https://github.com/tiangolo/full-stack-fastapi-couchbase
+
+⚠️ **ПРЕДУПРЕЖДЕНИЕ** ⚠️
+
+Если Вы начинаете новый проект, ознакомьтесь с представленными здесь альтернативами.
+
+Например, генератор проектов Full Stack FastAPI PostgreSQL может быть более подходящей альтернативой, так как он активно поддерживается и используется. И он включает в себя все новые возможности и улучшения.
+
+Но никто не запрещает Вам использовать генератор с СУБД Couchbase, возможно, он всё ещё работает нормально. Или у Вас уже есть проект, созданный с помощью этого генератора ранее, и Вы, вероятно, уже обновили его в соответствии со своими потребностями.
+
+Вы можете прочитать о нём больше в документации соответствующего репозитория.
+
+## Full Stack FastAPI MongoDB
+
+...может быть когда-нибудь появится, в зависимости от наличия у меня свободного времени и прочих факторов. 😅 🎉
+
+## Модели машинного обучения на основе spaCy и FastAPI
+
+GitHub: https://github.com/microsoft/cookiecutter-spacy-fastapi
+
+### Модели машинного обучения на основе spaCy и FastAPI - Особенности
+
+* Интеграция с моделями **spaCy** NER.
+* Встроенный формат запросов к **когнитивному поиску Azure**.
+* **Готовый к реальной работе** веб-сервер Python использующий Uvicorn и Gunicorn.
+* Встроенное развёртывание на основе **Azure DevOps** Kubernetes (AKS) CI/CD.
+* **Многоязычность**. Лёгкий выбор одного из встроенных в spaCy языков во время настройки проекта.
+* **Легко подключить** модели из других фреймворков (Pytorch, Tensorflow) не ограничиваясь spaCy.
diff --git a/docs/ru/docs/tutorial/background-tasks.md b/docs/ru/docs/tutorial/background-tasks.md
index e608f6c8f..81efda786 100644
--- a/docs/ru/docs/tutorial/background-tasks.md
+++ b/docs/ru/docs/tutorial/background-tasks.md
@@ -57,18 +57,18 @@
**FastAPI** знает, что нужно сделать в каждом случае и как переиспользовать тот же объект `BackgroundTasks`, так чтобы все фоновые задачи собрались и запустились вместе в фоне:
-=== "Python 3.6 и выше"
-
- ```Python hl_lines="13 15 22 25"
- {!> ../../../docs_src/background_tasks/tutorial002.py!}
- ```
-
-=== "Python 3.10 и выше"
+=== "Python 3.10+"
```Python hl_lines="11 13 20 23"
{!> ../../../docs_src/background_tasks/tutorial002_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="13 15 22 25"
+ {!> ../../../docs_src/background_tasks/tutorial002.py!}
+ ```
+
В этом примере сообщения будут записаны в `log.txt` *после* того, как ответ сервера был отправлен.
Если бы в запросе была очередь `q`, она бы первой записалась в `log.txt` фоновой задачей (потому что вызывается в зависимости `get_query`).
diff --git a/docs/ru/docs/tutorial/body-fields.md b/docs/ru/docs/tutorial/body-fields.md
index e8507c171..674b8bde4 100644
--- a/docs/ru/docs/tutorial/body-fields.md
+++ b/docs/ru/docs/tutorial/body-fields.md
@@ -6,18 +6,18 @@
Сначала вы должны импортировать его:
-=== "Python 3.6 и выше"
-
- ```Python hl_lines="4"
- {!> ../../../docs_src/body_fields/tutorial001.py!}
- ```
-
-=== "Python 3.10 и выше"
+=== "Python 3.10+"
```Python hl_lines="2"
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body_fields/tutorial001.py!}
+ ```
+
!!! warning "Внимание"
Обратите внимание, что функция `Field` импортируется непосредственно из `pydantic`, а не из `fastapi`, как все остальные функции (`Query`, `Path`, `Body` и т.д.).
@@ -25,18 +25,18 @@
Вы можете использовать функцию `Field` с атрибутами модели:
-=== "Python 3.6 и выше"
-
- ```Python hl_lines="11-14"
- {!> ../../../docs_src/body_fields/tutorial001.py!}
- ```
-
-=== "Python 3.10 и выше"
+=== "Python 3.10+"
```Python hl_lines="9-12"
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="11-14"
+ {!> ../../../docs_src/body_fields/tutorial001.py!}
+ ```
+
Функция `Field` работает так же, как `Query`, `Path` и `Body`, у ее такие же параметры и т.д.
!!! note "Технические детали"
diff --git a/docs/ru/docs/tutorial/cookie-params.md b/docs/ru/docs/tutorial/cookie-params.md
index 75e9d9064..a6f2caa26 100644
--- a/docs/ru/docs/tutorial/cookie-params.md
+++ b/docs/ru/docs/tutorial/cookie-params.md
@@ -6,36 +6,36 @@
Сначала импортируйте `Cookie`:
-=== "Python 3.6 и выше"
-
- ```Python hl_lines="3"
- {!> ../../../docs_src/cookie_params/tutorial001.py!}
- ```
-
-=== "Python 3.10 и выше"
+=== "Python 3.10+"
```Python hl_lines="1"
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/cookie_params/tutorial001.py!}
+ ```
+
## Объявление параметров `Cookie`
Затем объявляйте параметры cookie, используя ту же структуру, что и с `Path` и `Query`.
Первое значение - это значение по умолчанию, вы можете передать все дополнительные параметры проверки или аннотации:
-=== "Python 3.6 и выше"
-
- ```Python hl_lines="9"
- {!> ../../../docs_src/cookie_params/tutorial001.py!}
- ```
-
-=== "Python 3.10 и выше"
+=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/cookie_params/tutorial001.py!}
+ ```
+
!!! note "Технические детали"
`Cookie` - это класс, родственный `Path` и `Query`. Он также наследуется от общего класса `Param`.
diff --git a/docs/ru/docs/tutorial/extra-data-types.md b/docs/ru/docs/tutorial/extra-data-types.md
new file mode 100644
index 000000000..efcbcb38a
--- /dev/null
+++ b/docs/ru/docs/tutorial/extra-data-types.md
@@ -0,0 +1,82 @@
+# Дополнительные типы данных
+
+До сих пор вы использовали простые типы данных, такие как:
+
+* `int`
+* `float`
+* `str`
+* `bool`
+
+Но вы также можете использовать и более сложные типы.
+
+При этом у вас останутся те же возможности , что и до сих пор:
+
+* Отличная поддержка редактора.
+* Преобразование данных из входящих запросов.
+* Преобразование данных для ответа.
+* Валидация данных.
+* Автоматическая аннотация и документация.
+
+## Другие типы данных
+
+Ниже перечислены некоторые из дополнительных типов данных, которые вы можете использовать:
+
+* `UUID`:
+ * Стандартный "Универсальный уникальный идентификатор", используемый в качестве идентификатора во многих базах данных и системах.
+ * В запросах и ответах будет представлен как `str`.
+* `datetime.datetime`:
+ * Встроенный в Python `datetime.datetime`.
+ * В запросах и ответах будет представлен как `str` в формате ISO 8601, например: `2008-09-15T15:53:00+05:00`.
+* `datetime.date`:
+ * Встроенный в Python `datetime.date`.
+ * В запросах и ответах будет представлен как `str` в формате ISO 8601, например: `2008-09-15`.
+* `datetime.time`:
+ * Встроенный в Python `datetime.time`.
+ * В запросах и ответах будет представлен как `str` в формате ISO 8601, например: `14:23:55.003`.
+* `datetime.timedelta`:
+ * Встроенный в Python `datetime.timedelta`.
+ * В запросах и ответах будет представлен в виде общего количества секунд типа `float`.
+ * Pydantic также позволяет представить его как "Кодировку разницы во времени ISO 8601", см. документацию для получения дополнительной информации.
+* `frozenset`:
+ * В запросах и ответах обрабатывается так же, как и `set`:
+ * В запросах будет прочитан список, исключены дубликаты и преобразован в `set`.
+ * В ответах `set` будет преобразован в `list`.
+ * В сгенерированной схеме будет указано, что значения `set` уникальны (с помощью JSON-схемы `uniqueItems`).
+* `bytes`:
+ * Встроенный в Python `bytes`.
+ * В запросах и ответах будет рассматриваться как `str`.
+ * В сгенерированной схеме будет указано, что это `str` в формате `binary`.
+* `Decimal`:
+ * Встроенный в Python `Decimal`.
+ * В запросах и ответах обрабатывается так же, как и `float`.
+* Вы можете проверить все допустимые типы данных pydantic здесь: Типы данных Pydantic.
+
+## Пример
+
+Вот пример *операции пути* с параметрами, который демонстрирует некоторые из вышеперечисленных типов.
+
+=== "Python 3.6 и выше"
+
+ ```Python hl_lines="1 3 12-16"
+ {!> ../../../docs_src/extra_data_types/tutorial001.py!}
+ ```
+
+=== "Python 3.10 и выше"
+
+ ```Python hl_lines="1 2 11-15"
+ {!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
+ ```
+
+Обратите внимание, что параметры внутри функции имеют свой естественный тип данных, и вы, например, можете выполнять обычные манипуляции с датами, такие как:
+
+=== "Python 3.6 и выше"
+
+ ```Python hl_lines="18-19"
+ {!> ../../../docs_src/extra_data_types/tutorial001.py!}
+ ```
+
+=== "Python 3.10 и выше"
+
+ ```Python hl_lines="17-18"
+ {!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
+ ```
diff --git a/docs/ru/docs/tutorial/query-params-str-validations.md b/docs/ru/docs/tutorial/query-params-str-validations.md
new file mode 100644
index 000000000..68042db63
--- /dev/null
+++ b/docs/ru/docs/tutorial/query-params-str-validations.md
@@ -0,0 +1,919 @@
+# Query-параметры и валидация строк
+
+**FastAPI** позволяет определять дополнительную информацию и валидацию для ваших параметров.
+
+Давайте рассмотрим следующий пример:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial001.py!}
+ ```
+
+Query-параметр `q` имеет тип `Union[str, None]` (или `str | None` в Python 3.10). Это означает, что входной параметр будет типа `str`, но может быть и `None`. Ещё параметр имеет значение по умолчанию `None`, из-за чего FastAPI определит параметр как необязательный.
+
+!!! note "Технические детали"
+ FastAPI определит параметр `q` как необязательный, потому что его значение по умолчанию `= None`.
+
+ `Union` в `Union[str, None]` позволит редактору кода оказать вам лучшую поддержку и найти ошибки.
+
+## Расширенная валидация
+
+Добавим дополнительное условие валидации параметра `q` - **длина строки не более 50 символов** (условие проверяется всякий раз, когда параметр `q` не является `None`).
+
+### Импорт `Query` и `Annotated`
+
+Чтобы достичь этого, первым делом нам нужно импортировать:
+
+* `Query` из пакета `fastapi`:
+* `Annotated` из пакета `typing` (или из `typing_extensions` для Python ниже 3.9)
+
+=== "Python 3.10+"
+
+ В Python 3.9 или выше, `Annotated` является частью стандартной библиотеки, таким образом вы можете импортировать его из `typing`.
+
+ ```Python hl_lines="1 3"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002_an_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ В версиях Python ниже Python 3.9 `Annotation` импортируется из `typing_extensions`.
+
+ Эта библиотека будет установлена вместе с FastAPI.
+
+ ```Python hl_lines="3-4"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002_an.py!}
+ ```
+
+## `Annotated` как тип для query-параметра `q`
+
+Помните, как ранее я говорил об Annotated? Он может быть использован для добавления метаданных для ваших параметров в разделе [Введение в аннотации типов Python](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}?
+
+Пришло время использовать их в FastAPI. 🚀
+
+У нас была аннотация следующего типа:
+
+=== "Python 3.10+"
+
+ ```Python
+ q: str | None = None
+ ```
+
+=== "Python 3.6+"
+
+ ```Python
+ q: Union[str, None] = None
+ ```
+
+Вот что мы получим, если обернём это в `Annotated`:
+
+=== "Python 3.10+"
+
+ ```Python
+ q: Annotated[str | None] = None
+ ```
+
+=== "Python 3.6+"
+
+ ```Python
+ q: Annotated[Union[str, None]] = None
+ ```
+
+Обе эти версии означают одно и тоже. `q` - это параметр, который может быть `str` или `None`, и по умолчанию он будет принимать `None`.
+
+Давайте повеселимся. 🎉
+
+## Добавим `Query` в `Annotated` для query-параметра `q`
+
+Теперь, когда у нас есть `Annotated`, где мы можем добавить больше метаданных, добавим `Query` со значением параметра `max_length` равным 50:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002_an_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002_an.py!}
+ ```
+
+Обратите внимание, что значение по умолчанию всё ещё `None`, так что параметр остаётся необязательным.
+
+Однако теперь, имея `Query(max_length=50)` внутри `Annotated`, мы говорим FastAPI, что мы хотим извлечь это значение из параметров query-запроса (что произойдёт в любом случае 🤷), и что мы хотим иметь **дополнительные условия валидации** для этого значения (для чего мы и делаем это - чтобы получить дополнительную валидацию). 😎
+
+Теперь FastAPI:
+
+* **Валидирует** (проверяет), что полученные данные состоят максимум из 50 символов
+* Показывает **исчерпывающую ошибку** (будет описание местонахождения ошибки и её причины) для клиента в случаях, когда данные не валидны
+* **Задокументирует** параметр в схему OpenAPI *операции пути* (что будет отображено в **UI автоматической документации**)
+
+## Альтернативный (устаревший) способ задать `Query` как значение по умолчанию
+
+В предыдущих версиях FastAPI (ниже 0.95.0) необходимо было использовать `Query` как значение по умолчанию для query-параметра. Так было вместо размещения его в `Annotated`, так что велика вероятность, что вам встретится такой код. Сейчас объясню.
+
+!!! tip "Подсказка"
+ При написании нового кода и везде где это возможно, используйте `Annotated`, как было описано ранее. У этого способа есть несколько преимуществ (о них дальше) и никаких недостатков. 🍰
+
+Вот как вы могли бы использовать `Query()` в качестве значения по умолчанию параметра вашей функции, установив для параметра `max_length` значение 50:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002.py!}
+ ```
+
+В таком случае (без использования `Annotated`), мы заменили значение по умолчанию с `None` на `Query()` в функции. Теперь нам нужно установить значение по умолчанию для query-параметра `Query(default=None)`, что необходимо для тех же целей, как когда ранее просто указывалось значение по умолчанию (по крайней мере, для FastAPI).
+
+Таким образом:
+
+```Python
+q: Union[str, None] = Query(default=None)
+```
+
+...делает параметр необязательным со значением по умолчанию `None`, также как это делает:
+
+```Python
+q: Union[str, None] = None
+```
+
+И для Python 3.10 и выше:
+
+```Python
+q: str | None = Query(default=None)
+```
+
+...делает параметр необязательным со значением по умолчанию `None`, также как это делает:
+
+```Python
+q: str | None = None
+```
+
+Но он явно объявляет его как query-параметр.
+
+!!! info "Дополнительная информация"
+ Запомните, важной частью объявления параметра как необязательного является:
+
+ ```Python
+ = None
+ ```
+
+ или:
+
+ ```Python
+ = Query(default=None)
+ ```
+
+ так как `None` указан в качестве значения по умолчанию, параметр будет **необязательным**.
+
+ `Union[str, None]` позволит редактору кода оказать вам лучшую поддержку. Но это не то, на что обращает внимание FastAPI для определения необязательности параметра.
+
+Теперь, мы можем указать больше параметров для `Query`. В данном случае, параметр `max_length` применяется к строкам:
+
+```Python
+q: Union[str, None] = Query(default=None, max_length=50)
+```
+
+Входные данные будут проверены. Если данные недействительны, тогда будет указано на ошибку в запросе (будет описание местонахождения ошибки и её причины). Кроме того, параметр задокументируется в схеме OpenAPI данной *операции пути*.
+
+### Использовать `Query` как значение по умолчанию или добавить в `Annotated`
+
+Когда `Query` используется внутри `Annotated`, вы не можете использовать параметр `default` у `Query`.
+
+Вместо этого, используйте обычное указание значения по умолчанию для параметра функции. Иначе, это будет несовместимо.
+
+Следующий пример не рабочий:
+
+```Python
+q: Annotated[str, Query(default="rick")] = "morty"
+```
+
+...потому что нельзя однозначно определить, что именно должно быть значением по умолчанию: `"rick"` или `"morty"`.
+
+Вам следует использовать (предпочтительно):
+
+```Python
+q: Annotated[str, Query()] = "rick"
+```
+
+...или как в старом коде, который вам может попасться:
+
+```Python
+q: str = Query(default="rick")
+```
+
+### Преимущества `Annotated`
+
+**Рекомендуется использовать `Annotated`** вместо значения по умолчанию в параметрах функции, потому что так **лучше** по нескольким причинам. 🤓
+
+Значение **по умолчанию** у **параметров функции** - это **действительно значение по умолчанию**, что более интуитивно понятно для пользователей Python. 😌
+
+Вы можете **вызвать** ту же функцию в **иных местах** без FastAPI, и она **сработает как ожидается**. Если это **обязательный** параметр (без значения по умолчанию), ваш **редактор кода** сообщит об ошибке. **Python** также укажет на ошибку, если вы вызовете функцию без передачи ей обязательного параметра.
+
+Если вы вместо `Annotated` используете **(устаревший) стиль значений по умолчанию**, тогда при вызове этой функции без FastAPI в **другом месте** вам необходимо **помнить** о передаче аргументов функции, чтобы она работала корректно. В противном случае, значения будут отличаться от тех, что вы ожидаете (например, `QueryInfo` или что-то подобное вместо `str`). И ни ваш редактор кода, ни Python не будут жаловаться на работу этой функции, только когда вычисления внутри дадут сбой.
+
+Так как `Annotated` может принимать более одной аннотации метаданных, то теперь вы можете использовать ту же функцию с другими инструментами, например Typer. 🚀
+
+## Больше валидации
+
+Вы также можете добавить параметр `min_length`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial003_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial003.py!}
+ ```
+
+## Регулярные выражения
+
+Вы можете определить регулярное выражение, которому должен соответствовать параметр:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial004_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial004_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/query_params_str_validations/tutorial004_an.py!}
+ ```
+
+=== "Python 3.10+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.6+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial004.py!}
+ ```
+
+Данное регулярное выражение проверяет, что полученное значение параметра:
+
+* `^`: начало строки.
+* `fixedquery`: в точности содержит строку `fixedquery`.
+* `$`: конец строки, не имеет символов после `fixedquery`.
+
+Не переживайте, если **"регулярное выражение"** вызывает у вас трудности. Это достаточно сложная тема для многих людей. Вы можете сделать множество вещей без использования регулярных выражений.
+
+Но когда они вам понадобятся, и вы закончите их освоение, то не будет проблемой использовать их в **FastAPI**.
+
+## Значения по умолчанию
+
+Вы точно также можете указать любое значение `по умолчанию`, как ранее указывали `None`.
+
+Например, вы хотите для параметра запроса `q` указать, что он должен состоять минимум из 3 символов (`min_length=3`) и иметь значение по умолчанию `"fixedquery"`:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial005_an.py!}
+ ```
+
+=== "Python 3.6+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial005.py!}
+ ```
+
+!!! note "Технические детали"
+ Наличие значения по умолчанию делает параметр необязательным.
+
+## Обязательный параметр
+
+Когда вам не требуется дополнительная валидация или дополнительные метаданные для параметра запроса, вы можете сделать параметр `q` обязательным просто не указывая значения по умолчанию. Например:
+
+```Python
+q: str
+```
+
+вместо:
+
+```Python
+q: Union[str, None] = None
+```
+
+Но у нас query-параметр определён как `Query`. Например:
+
+=== "Annotated"
+
+ ```Python
+ q: Annotated[Union[str, None], Query(min_length=3)] = None
+ ```
+
+=== "без Annotated"
+
+ ```Python
+ q: Union[str, None] = Query(default=None, min_length=3)
+ ```
+
+В таком случае, чтобы сделать query-параметр `Query` обязательным, вы можете просто не указывать значение по умолчанию:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006_an.py!}
+ ```
+
+=== "Python 3.6+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006.py!}
+ ```
+
+ !!! tip "Подсказка"
+ Обратите внимание, что даже когда `Query()` используется как значение по умолчанию для параметра функции, мы не передаём `default=None` в `Query()`.
+
+ Лучше будет использовать версию с `Annotated`. 😉
+
+### Обязательный параметр с Ellipsis (`...`)
+
+Альтернативный способ указать обязательность параметра запроса - это указать параметр `default` через многоточие `...`:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006b_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006b_an.py!}
+ ```
+
+=== "Python 3.6+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006b.py!}
+ ```
+
+!!! info "Дополнительная информация"
+ Если вы ранее не сталкивались с `...`: это специальное значение, часть языка Python и называется "Ellipsis".
+
+ Используется в Pydantic и FastAPI для определения, что значение требуется обязательно.
+
+Таким образом, **FastAPI** определяет, что параметр является обязательным.
+
+### Обязательный параметр с `None`
+
+Вы можете определить, что параметр может принимать `None`, но всё ещё является обязательным. Это может потребоваться для того, чтобы пользователи явно указали параметр, даже если его значение будет `None`.
+
+Чтобы этого добиться, вам нужно определить `None` как валидный тип для параметра запроса, но также указать `default=...`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006c_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006c_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006c_an.py!}
+ ```
+
+=== "Python 3.10+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006c_py310.py!}
+ ```
+
+=== "Python 3.6+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006c.py!}
+ ```
+
+!!! tip "Подсказка"
+ Pydantic, мощь которого используется в FastAPI для валидации и сериализации, имеет специальное поведение для `Optional` или `Union[Something, None]` без значения по умолчанию. Вы можете узнать об этом больше в документации Pydantic, раздел Обязательные Опциональные поля.
+
+### Использование Pydantic's `Required` вместо Ellipsis (`...`)
+
+Если вас смущает `...`, вы можете использовать `Required` из Pydantic:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="4 10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006d_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="2 9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006d_an.py!}
+ ```
+
+=== "Python 3.6+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="2 8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006d.py!}
+ ```
+
+!!! tip "Подсказка"
+ Запомните, когда вам необходимо объявить query-параметр обязательным, вы можете просто не указывать параметр `default`. Таким образом, вам редко придётся использовать `...` или `Required`.
+
+## Множество значений для query-параметра
+
+Для query-параметра `Query` можно указать, что он принимает список значений (множество значений).
+
+Например, query-параметр `q` может быть указан в URL несколько раз. И если вы ожидаете такой формат запроса, то можете указать это следующим образом:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011_an.py!}
+ ```
+
+=== "Python 3.10+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011_py310.py!}
+ ```
+
+=== "Python 3.9+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011_py39.py!}
+ ```
+
+=== "Python 3.6+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011.py!}
+ ```
+
+Затем, получив такой URL:
+
+```
+http://localhost:8000/items/?q=foo&q=bar
+```
+
+вы бы получили несколько значений (`foo` и `bar`), которые относятся к параметру `q`, в виде Python `list` внутри вашей *функции обработки пути*, в *параметре функции* `q`.
+
+Таким образом, ответ на этот URL будет:
+
+```JSON
+{
+ "q": [
+ "foo",
+ "bar"
+ ]
+}
+```
+
+!!! tip "Подсказка"
+ Чтобы объявить query-параметр типом `list`, как в примере выше, вам нужно явно использовать `Query`, иначе он будет интерпретирован как тело запроса.
+
+Интерактивная документация API будет обновлена соответствующим образом, где будет разрешено множество значений:
+
+
+
+### Query-параметр со множеством значений по умолчанию
+
+Вы также можете указать тип `list` со списком значений по умолчанию на случай, если вам их не предоставят:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial012_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial012_an.py!}
+ ```
+
+=== "Python 3.9+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial012_py39.py!}
+ ```
+
+=== "Python 3.6+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial012.py!}
+ ```
+
+Если вы перейдёте по ссылке:
+
+```
+http://localhost:8000/items/
+```
+
+значение по умолчанию для `q` будет: `["foo", "bar"]` и ответом для вас будет:
+
+```JSON
+{
+ "q": [
+ "foo",
+ "bar"
+ ]
+}
+```
+
+#### Использование `list`
+
+Вы также можете использовать `list` напрямую вместо `List[str]` (или `list[str]` в Python 3.9+):
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial013_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial013_an.py!}
+ ```
+
+=== "Python 3.6+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial013.py!}
+ ```
+
+!!! note "Технические детали"
+ Запомните, что в таком случае, FastAPI не будет проверять содержимое списка.
+
+ Например, для List[int] список будет провалидирован (и задокументирован) на содержание только целочисленных элементов. Но для простого `list` такой проверки не будет.
+
+## Больше метаданных
+
+Вы можете добавить больше информации об query-параметре.
+
+Указанная информация будет включена в генерируемую OpenAPI документацию и использована в пользовательском интерфейсе и внешних инструментах.
+
+!!! note "Технические детали"
+ Имейте в виду, что разные инструменты могут иметь разные уровни поддержки OpenAPI.
+
+ Некоторые из них могут не отображать (на данный момент) всю заявленную дополнительную информацию, хотя в большинстве случаев отсутствующая функция уже запланирована к разработке.
+
+Вы можете указать название query-параметра, используя параметр `title`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial007_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial007_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial007_an.py!}
+ ```
+
+=== "Python 3.10+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial007_py310.py!}
+ ```
+
+=== "Python 3.6+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial007.py!}
+ ```
+
+Добавить описание, используя параметр `description`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/query_params_str_validations/tutorial008_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/query_params_str_validations/tutorial008_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="15"
+ {!> ../../../docs_src/query_params_str_validations/tutorial008_an.py!}
+ ```
+
+=== "Python 3.10+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/query_params_str_validations/tutorial008_py310.py!}
+ ```
+
+=== "Python 3.6+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/query_params_str_validations/tutorial008.py!}
+ ```
+
+## Псевдонимы параметров
+
+Представьте, что вы хотите использовать query-параметр с названием `item-query`.
+
+Например:
+
+```
+http://127.0.0.1:8000/items/?item-query=foobaritems
+```
+
+Но `item-query` является невалидным именем переменной в Python.
+
+Наиболее похожее валидное имя `item_query`.
+
+Но вам всё равно необходим `item-query`...
+
+Тогда вы можете объявить `псевдоним`, и этот псевдоним будет использоваться для поиска значения параметра запроса:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial009_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial009_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial009_an.py!}
+ ```
+
+=== "Python 3.10+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial009_py310.py!}
+ ```
+
+=== "Python 3.6+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial009.py!}
+ ```
+
+## Устаревшие параметры
+
+Предположим, вы больше не хотите использовать какой-либо параметр.
+
+Вы решили оставить его, потому что клиенты всё ещё им пользуются. Но вы хотите отобразить это в документации как устаревший функционал.
+
+Тогда для `Query` укажите параметр `deprecated=True`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/query_params_str_validations/tutorial010_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/query_params_str_validations/tutorial010_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/query_params_str_validations/tutorial010_an.py!}
+ ```
+
+=== "Python 3.10+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/query_params_str_validations/tutorial010_py310.py!}
+ ```
+
+=== "Python 3.6+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/query_params_str_validations/tutorial010.py!}
+ ```
+
+В документации это будет отображено следующим образом:
+
+
+
+## Исключить из OpenAPI
+
+Чтобы исключить query-параметр из генерируемой OpenAPI схемы (а также из системы автоматической генерации документации), укажите в `Query` параметр `include_in_schema=False`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial014_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial014_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial014_an.py!}
+ ```
+
+=== "Python 3.10+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial014_py310.py!}
+ ```
+
+=== "Python 3.6+ без Annotated"
+
+ !!! tip "Подсказка"
+ Рекомендуется использовать версию с `Annotated` если возможно.
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial014.py!}
+ ```
+
+## Резюме
+
+Вы можете объявлять дополнительные правила валидации и метаданные для ваших параметров запроса.
+
+Общие метаданные:
+
+* `alias`
+* `title`
+* `description`
+* `deprecated`
+* `include_in_schema`
+
+Специфичные правила валидации для строк:
+
+* `min_length`
+* `max_length`
+* `regex`
+
+В рассмотренных примерах показано объявление правил валидации для строковых значений `str`.
+
+В следующих главах вы увидете, как объявлять правила валидации для других типов (например, чисел).
diff --git a/docs/ru/mkdocs.yml b/docs/ru/mkdocs.yml
index 4b9727872..0423643d6 100644
--- a/docs/ru/mkdocs.yml
+++ b/docs/ru/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -64,15 +65,21 @@ nav:
- fastapi-people.md
- python-types.md
- Учебник - руководство пользователя:
+ - tutorial/query-params-str-validations.md
- tutorial/body-fields.md
- tutorial/background-tasks.md
+ - tutorial/extra-data-types.md
- tutorial/cookie-params.md
- async.md
- Развёртывание:
- deployment/index.md
- deployment/versions.md
+- project-generation.md
+- alternatives.md
- history-design-future.md
- external-links.md
+- benchmarks.md
+- help-fastapi.md
- contributing.md
markdown_extensions:
- toc:
@@ -119,6 +126,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/sq/mkdocs.yml b/docs/sq/mkdocs.yml
index f24c7c503..2766b0adf 100644
--- a/docs/sq/mkdocs.yml
+++ b/docs/sq/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -105,6 +106,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/sv/mkdocs.yml b/docs/sv/mkdocs.yml
index 574cc5abd..5aa37ece6 100644
--- a/docs/sv/mkdocs.yml
+++ b/docs/sv/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -105,6 +106,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/ta/mkdocs.yml b/docs/ta/mkdocs.yml
index e31821e4b..884115044 100644
--- a/docs/ta/mkdocs.yml
+++ b/docs/ta/mkdocs.yml
@@ -41,10 +41,12 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
- he: /he/
+ - hy: /hy/
- id: /id/
- it: /it/
- ja: /ja/
@@ -81,7 +83,7 @@ markdown_extensions:
extra:
analytics:
provider: google
- property: UA-133183413-1
+ property: G-YNEVN69SC3
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
@@ -104,6 +106,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
@@ -112,6 +116,8 @@ extra:
name: fr - français
- link: /he/
name: he
+ - link: /hy/
+ name: hy
- link: /id/
name: id
- link: /it/
diff --git a/docs/tr/mkdocs.yml b/docs/tr/mkdocs.yml
index 19dcf2099..23d6b9708 100644
--- a/docs/tr/mkdocs.yml
+++ b/docs/tr/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -110,6 +111,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/uk/mkdocs.yml b/docs/uk/mkdocs.yml
index b8152e821..e9339997f 100644
--- a/docs/uk/mkdocs.yml
+++ b/docs/uk/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -105,6 +106,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md
index 5813272ee..f404820df 100644
--- a/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md
+++ b/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md
@@ -6,18 +6,18 @@
在前面的例子中, 我们从依赖项 ("可依赖对象") 中返回了一个 `dict`:
-=== "Python 3.6 以及 以上"
-
- ```Python hl_lines="9"
- {!> ../../../docs_src/dependencies/tutorial001.py!}
- ```
-
-=== "Python 3.10 以及以上"
+=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
但是后面我们在路径操作函数的参数 `commons` 中得到了一个 `dict`。
我们知道编辑器不能为 `dict` 提供很多支持(比如补全),因为编辑器不知道 `dict` 的键和值类型。
@@ -79,46 +79,46 @@ fluffy = Cat(name="Mr Fluffy")
所以,我们可以将上面的依赖项 "可依赖对象" `common_parameters` 更改为类 `CommonQueryParams`:
-=== "Python 3.6 以及 以上"
-
- ```Python hl_lines="11-15"
- {!> ../../../docs_src/dependencies/tutorial002.py!}
- ```
-
-=== "Python 3.10 以及 以上"
+=== "Python 3.10+"
```Python hl_lines="9-13"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
-注意用于创建类实例的 `__init__` 方法:
+=== "Python 3.6+"
-=== "Python 3.6 以及 以上"
-
- ```Python hl_lines="12"
+ ```Python hl_lines="11-15"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
-=== "Python 3.10 以及 以上"
+注意用于创建类实例的 `__init__` 方法:
+
+=== "Python 3.10+"
```Python hl_lines="10"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
-...它与我们以前的 `common_parameters` 具有相同的参数:
+=== "Python 3.6+"
-=== "Python 3.6 以及 以上"
-
- ```Python hl_lines="9"
- {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/dependencies/tutorial002.py!}
```
-=== "Python 3.10 以及 以上"
+...它与我们以前的 `common_parameters` 具有相同的参数:
+
+=== "Python 3.10+"
```Python hl_lines="6"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
这些参数就是 **FastAPI** 用来 "处理" 依赖项的。
在两个例子下,都有:
@@ -133,18 +133,18 @@ fluffy = Cat(name="Mr Fluffy")
现在,您可以使用这个类来声明你的依赖项了。
-=== "Python 3.6 以及 以上"
-
- ```Python hl_lines="19"
- {!> ../../../docs_src/dependencies/tutorial002.py!}
- ```
-
-=== "Python 3.10 以及 以上"
+=== "Python 3.10+"
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial002.py!}
+ ```
+
**FastAPI** 调用 `CommonQueryParams` 类。这将创建该类的一个 "实例",该实例将作为参数 `commons` 被传递给你的函数。
## 类型注解 vs `Depends`
@@ -183,18 +183,18 @@ commons = Depends(CommonQueryParams)
..就像:
-=== "Python 3.6 以及 以上"
-
- ```Python hl_lines="19"
- {!> ../../../docs_src/dependencies/tutorial003.py!}
- ```
-
-=== "Python 3.10 以及 以上"
+=== "Python 3.10+"
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial003_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial003.py!}
+ ```
+
但是声明类型是被鼓励的,因为那样你的编辑器就会知道将传递什么作为参数 `commons` ,然后它可以帮助你完成代码,类型检查,等等:
@@ -227,18 +227,18 @@ commons: CommonQueryParams = Depends()
同样的例子看起来像这样:
-=== "Python 3.6 以及 以上"
-
- ```Python hl_lines="19"
- {!> ../../../docs_src/dependencies/tutorial004.py!}
- ```
-
-=== "Python 3.10 以及 以上"
+=== "Python 3.10+"
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial004_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial004.py!}
+ ```
+
... **FastAPI** 会知道怎么处理。
!!! tip
diff --git a/docs/zh/docs/tutorial/encoder.md b/docs/zh/docs/tutorial/encoder.md
index cb813940c..76ed846ce 100644
--- a/docs/zh/docs/tutorial/encoder.md
+++ b/docs/zh/docs/tutorial/encoder.md
@@ -20,18 +20,18 @@
它接收一个对象,比如Pydantic模型,并会返回一个JSON兼容的版本:
-=== "Python 3.6 and above"
-
- ```Python hl_lines="5 22"
- {!> ../../../docs_src/encoder/tutorial001.py!}
- ```
-
-=== "Python 3.10 and above"
+=== "Python 3.10+"
```Python hl_lines="4 21"
{!> ../../../docs_src/encoder/tutorial001_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="5 22"
+ {!> ../../../docs_src/encoder/tutorial001.py!}
+ ```
+
在这个例子中,它将Pydantic模型转换为`dict`,并将`datetime`转换为`str`。
调用它的结果后就可以使用Python标准编码中的`json.dumps()`。
diff --git a/docs/zh/docs/tutorial/request-files.md b/docs/zh/docs/tutorial/request-files.md
index e18d6fc9f..03474907e 100644
--- a/docs/zh/docs/tutorial/request-files.md
+++ b/docs/zh/docs/tutorial/request-files.md
@@ -124,18 +124,18 @@ contents = myfile.file.read()
您可以通过使用标准类型注解并将 None 作为默认值的方式将一个文件参数设为可选:
-=== "Python 3.6 及以上版本"
-
- ```Python hl_lines="9 17"
- {!> ../../../docs_src/request_files/tutorial001_02.py!}
- ```
-
-=== "Python 3.9 及以上版本"
+=== "Python 3.9+"
```Python hl_lines="7 14"
{!> ../../../docs_src/request_files/tutorial001_02_py310.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 17"
+ {!> ../../../docs_src/request_files/tutorial001_02.py!}
+ ```
+
## 带有额外元数据的 `UploadFile`
您也可以将 `File()` 与 `UploadFile` 一起使用,例如,设置额外的元数据:
@@ -152,18 +152,18 @@ FastAPI 支持同时上传多个文件。
上传多个文件时,要声明含 `bytes` 或 `UploadFile` 的列表(`List`):
-=== "Python 3.6 及以上版本"
-
- ```Python hl_lines="10 15"
- {!> ../../../docs_src/request_files/tutorial002.py!}
- ```
-
-=== "Python 3.9 及以上版本"
+=== "Python 3.9+"
```Python hl_lines="8 13"
{!> ../../../docs_src/request_files/tutorial002_py39.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="10 15"
+ {!> ../../../docs_src/request_files/tutorial002.py!}
+ ```
+
接收的也是含 `bytes` 或 `UploadFile` 的列表(`list`)。
@@ -177,18 +177,18 @@ FastAPI 支持同时上传多个文件。
和之前的方式一样, 您可以为 `File()` 设置额外参数, 即使是 `UploadFile`:
-=== "Python 3.6 及以上版本"
-
- ```Python hl_lines="18"
- {!> ../../../docs_src/request_files/tutorial003.py!}
- ```
-
-=== "Python 3.9 及以上版本"
+=== "Python 3.9+"
```Python hl_lines="16"
{!> ../../../docs_src/request_files/tutorial003_py39.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/request_files/tutorial003.py!}
+ ```
+
## 小结
本节介绍了如何用 `File` 把上传文件声明为(表单数据的)输入参数。
diff --git a/docs/zh/docs/tutorial/sql-databases.md b/docs/zh/docs/tutorial/sql-databases.md
index 6b354c2b6..482588f94 100644
--- a/docs/zh/docs/tutorial/sql-databases.md
+++ b/docs/zh/docs/tutorial/sql-databases.md
@@ -246,22 +246,22 @@ connect_args={"check_same_thread": False}
但是为了安全起见,`password`不会出现在其他同类 Pydantic*模型*中,例如用户请求时不应该从 API 返回响应中包含它。
-=== "Python 3.6 及以上版本"
+=== "Python 3.10+"
- ```Python hl_lines="3 6-8 11-12 23-24 27-28"
- {!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
+ ```Python hl_lines="1 4-6 9-10 21-22 25-26"
+ {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```
-=== "Python 3.9 及以上版本"
+=== "Python 3.9+"
```Python hl_lines="3 6-8 11-12 23-24 27-28"
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
```
-=== "Python 3.10 及以上版本"
+=== "Python 3.6+"
- ```Python hl_lines="1 4-6 9-10 21-22 25-26"
- {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
+ ```Python hl_lines="3 6-8 11-12 23-24 27-28"
+ {!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```
#### SQLAlchemy 风格和 Pydantic 风格
@@ -290,22 +290,22 @@ name: str
不仅是这些项目的 ID,还有我们在 Pydantic*模型*中定义的用于读取项目的所有数据:`Item`.
-=== "Python 3.6 及以上版本"
+=== "Python 3.10+"
- ```Python hl_lines="15-17 31-34"
- {!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
+ ```Python hl_lines="13-15 29-32"
+ {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```
-=== "Python 3.9 及以上版本"
+=== "Python 3.9+"
```Python hl_lines="15-17 31-34"
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
```
-=== "Python 3.10 及以上版本"
+=== "Python 3.6+"
- ```Python hl_lines="13-15 29-32"
- {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
+ ```Python hl_lines="15-17 31-34"
+ {!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```
!!! tip
@@ -319,22 +319,22 @@ name: str
在`Config`类中,设置属性`orm_mode = True`。
-=== "Python 3.6 及以上版本"
+=== "Python 3.10+"
- ```Python hl_lines="15 19-20 31 36-37"
- {!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
+ ```Python hl_lines="13 17-18 29 34-35"
+ {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```
-=== "Python 3.9 及以上版本"
+=== "Python 3.9+"
```Python hl_lines="15 19-20 31 36-37"
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
```
-=== "Python 3.10 及以上版本"
+=== "Python 3.6+"
- ```Python hl_lines="13 17-18 29 34-35"
- {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
+ ```Python hl_lines="15 19-20 31 36-37"
+ {!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```
!!! tip
@@ -465,18 +465,18 @@ current_user.items
以非常简单的方式创建数据库表:
-=== "Python 3.6 及以上版本"
-
- ```Python hl_lines="9"
- {!> ../../../docs_src/sql_databases/sql_app/main.py!}
- ```
-
-=== "Python 3.9 及以上版本"
+=== "Python 3.9+"
```Python hl_lines="7"
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/sql_databases/sql_app/main.py!}
+ ```
+
#### Alembic 注意
通常你可能会使用 Alembic,来进行格式化数据库(创建表等)。
@@ -499,18 +499,18 @@ current_user.items
我们的依赖项将创建一个新的 SQLAlchemy `SessionLocal`,它将在单个请求中使用,然后在请求完成后关闭它。
-=== "Python 3.6 及以上版本"
-
- ```Python hl_lines="15-20"
- {!> ../../../docs_src/sql_databases/sql_app/main.py!}
- ```
-
-=== "Python 3.9 及以上版本"
+=== "Python 3.9+"
```Python hl_lines="13-18"
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="15-20"
+ {!> ../../../docs_src/sql_databases/sql_app/main.py!}
+ ```
+
!!! info
我们将`SessionLocal()`请求的创建和处理放在一个`try`块中。
@@ -524,18 +524,18 @@ current_user.items
*这将为我们在路径操作函数*中提供更好的编辑器支持,因为编辑器将知道`db`参数的类型`Session`:
-=== "Python 3.6 及以上版本"
-
- ```Python hl_lines="24 32 38 47 53"
- {!> ../../../docs_src/sql_databases/sql_app/main.py!}
- ```
-
-=== "Python 3.9 及以上版本"
+=== "Python 3.9+"
```Python hl_lines="22 30 36 45 51"
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="24 32 38 47 53"
+ {!> ../../../docs_src/sql_databases/sql_app/main.py!}
+ ```
+
!!! info "技术细节"
参数`db`实际上是 type `SessionLocal`,但是这个类(用 创建`sessionmaker()`)是 SQLAlchemy 的“代理” `Session`,所以,编辑器并不真正知道提供了哪些方法。
@@ -545,18 +545,18 @@ current_user.items
现在,到了最后,编写标准的**FastAPI** *路径操作*代码。
-=== "Python 3.6 及以上版本"
-
- ```Python hl_lines="23-28 31-34 37-42 45-49 52-55"
- {!> ../../../docs_src/sql_databases/sql_app/main.py!}
- ```
-
-=== "Python 3.9 及以上版本"
+=== "Python 3.9+"
```Python hl_lines="21-26 29-32 35-40 43-47 50-53"
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="23-28 31-34 37-42 45-49 52-55"
+ {!> ../../../docs_src/sql_databases/sql_app/main.py!}
+ ```
+
我们在依赖项中的每个请求之前利用`yield`创建数据库会话,然后关闭它。
所以我们就可以在*路径操作函数*中创建需要的依赖,就能直接获取会话。
@@ -638,22 +638,22 @@ def read_user(user_id: int, db: Session = Depends(get_db)):
* `sql_app/schemas.py`:
-=== "Python 3.6 及以上版本"
+=== "Python 3.10+"
```Python
- {!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
+ {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```
-=== "Python 3.9 及以上版本"
+=== "Python 3.9+"
```Python
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
```
-=== "Python 3.10 及以上版本"
+=== "Python 3.6+"
```Python
- {!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
+ {!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```
* `sql_app/crud.py`:
@@ -664,18 +664,18 @@ def read_user(user_id: int, db: Session = Depends(get_db)):
* `sql_app/main.py`:
-=== "Python 3.6 及以上版本"
-
- ```Python
- {!> ../../../docs_src/sql_databases/sql_app/main.py!}
- ```
-
-=== "Python 3.9 及以上版本"
+=== "Python 3.9+"
```Python
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
+=== "Python 3.6+"
+
+ ```Python
+ {!> ../../../docs_src/sql_databases/sql_app/main.py!}
+ ```
+
## 执行项目
您可以复制这些代码并按原样使用它。
@@ -723,18 +723,18 @@ $ uvicorn sql_app.main:app --reload
我们将添加中间件(只是一个函数)将为每个请求创建一个新的 SQLAlchemy`SessionLocal`,将其添加到请求中,然后在请求完成后关闭它。
-=== "Python 3.6 及以上版本"
-
- ```Python hl_lines="14-22"
- {!> ../../../docs_src/sql_databases/sql_app/alt_main.py!}
- ```
-
-=== "Python 3.9 及以上版本"
+=== "Python 3.9+"
```Python hl_lines="12-20"
{!> ../../../docs_src/sql_databases/sql_app_py39/alt_main.py!}
```
+=== "Python 3.6+"
+
+ ```Python hl_lines="14-22"
+ {!> ../../../docs_src/sql_databases/sql_app/alt_main.py!}
+ ```
+
!!! info
我们将`SessionLocal()`请求的创建和处理放在一个`try`块中。
diff --git a/docs/zh/mkdocs.yml b/docs/zh/mkdocs.yml
index d25881c43..906fcf1d6 100644
--- a/docs/zh/mkdocs.yml
+++ b/docs/zh/mkdocs.yml
@@ -41,6 +41,7 @@ nav:
- en: /
- az: /az/
- de: /de/
+ - em: /em/
- es: /es/
- fa: /fa/
- fr: /fr/
@@ -162,6 +163,8 @@ extra:
name: az
- link: /de/
name: de
+ - link: /em/
+ name: 😉
- link: /es/
name: es - español
- link: /fa/
diff --git a/docs_src/additional_status_codes/tutorial001_an.py b/docs_src/additional_status_codes/tutorial001_an.py
new file mode 100644
index 000000000..b5ad6a16b
--- /dev/null
+++ b/docs_src/additional_status_codes/tutorial001_an.py
@@ -0,0 +1,26 @@
+from typing import Union
+
+from fastapi import Body, FastAPI, status
+from fastapi.responses import JSONResponse
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "size": 3}}
+
+
+@app.put("/items/{item_id}")
+async def upsert_item(
+ item_id: str,
+ name: Annotated[Union[str, None], Body()] = None,
+ size: Annotated[Union[int, None], Body()] = None,
+):
+ if item_id in items:
+ item = items[item_id]
+ item["name"] = name
+ item["size"] = size
+ return item
+ else:
+ item = {"name": name, "size": size}
+ items[item_id] = item
+ return JSONResponse(status_code=status.HTTP_201_CREATED, content=item)
diff --git a/docs_src/additional_status_codes/tutorial001_an_py310.py b/docs_src/additional_status_codes/tutorial001_an_py310.py
new file mode 100644
index 000000000..1865074a1
--- /dev/null
+++ b/docs_src/additional_status_codes/tutorial001_an_py310.py
@@ -0,0 +1,25 @@
+from typing import Annotated
+
+from fastapi import Body, FastAPI, status
+from fastapi.responses import JSONResponse
+
+app = FastAPI()
+
+items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "size": 3}}
+
+
+@app.put("/items/{item_id}")
+async def upsert_item(
+ item_id: str,
+ name: Annotated[str | None, Body()] = None,
+ size: Annotated[int | None, Body()] = None,
+):
+ if item_id in items:
+ item = items[item_id]
+ item["name"] = name
+ item["size"] = size
+ return item
+ else:
+ item = {"name": name, "size": size}
+ items[item_id] = item
+ return JSONResponse(status_code=status.HTTP_201_CREATED, content=item)
diff --git a/docs_src/additional_status_codes/tutorial001_an_py39.py b/docs_src/additional_status_codes/tutorial001_an_py39.py
new file mode 100644
index 000000000..89653dd8a
--- /dev/null
+++ b/docs_src/additional_status_codes/tutorial001_an_py39.py
@@ -0,0 +1,25 @@
+from typing import Annotated, Union
+
+from fastapi import Body, FastAPI, status
+from fastapi.responses import JSONResponse
+
+app = FastAPI()
+
+items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "size": 3}}
+
+
+@app.put("/items/{item_id}")
+async def upsert_item(
+ item_id: str,
+ name: Annotated[Union[str, None], Body()] = None,
+ size: Annotated[Union[int, None], Body()] = None,
+):
+ if item_id in items:
+ item = items[item_id]
+ item["name"] = name
+ item["size"] = size
+ return item
+ else:
+ item = {"name": name, "size": size}
+ items[item_id] = item
+ return JSONResponse(status_code=status.HTTP_201_CREATED, content=item)
diff --git a/docs_src/additional_status_codes/tutorial001_py310.py b/docs_src/additional_status_codes/tutorial001_py310.py
new file mode 100644
index 000000000..38bfa455b
--- /dev/null
+++ b/docs_src/additional_status_codes/tutorial001_py310.py
@@ -0,0 +1,23 @@
+from fastapi import Body, FastAPI, status
+from fastapi.responses import JSONResponse
+
+app = FastAPI()
+
+items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "size": 3}}
+
+
+@app.put("/items/{item_id}")
+async def upsert_item(
+ item_id: str,
+ name: str | None = Body(default=None),
+ size: int | None = Body(default=None),
+):
+ if item_id in items:
+ item = items[item_id]
+ item["name"] = name
+ item["size"] = size
+ return item
+ else:
+ item = {"name": name, "size": size}
+ items[item_id] = item
+ return JSONResponse(status_code=status.HTTP_201_CREATED, content=item)
diff --git a/docs_src/app_testing/app_b_an/__init__.py b/docs_src/app_testing/app_b_an/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs_src/app_testing/app_b_an/main.py b/docs_src/app_testing/app_b_an/main.py
new file mode 100644
index 000000000..c63134fc9
--- /dev/null
+++ b/docs_src/app_testing/app_b_an/main.py
@@ -0,0 +1,39 @@
+from typing import Union
+
+from fastapi import FastAPI, Header, HTTPException
+from pydantic import BaseModel
+from typing_extensions import Annotated
+
+fake_secret_token = "coneofsilence"
+
+fake_db = {
+ "foo": {"id": "foo", "title": "Foo", "description": "There goes my hero"},
+ "bar": {"id": "bar", "title": "Bar", "description": "The bartenders"},
+}
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ id: str
+ title: str
+ description: Union[str, None] = None
+
+
+@app.get("/items/{item_id}", response_model=Item)
+async def read_main(item_id: str, x_token: Annotated[str, Header()]):
+ if x_token != fake_secret_token:
+ raise HTTPException(status_code=400, detail="Invalid X-Token header")
+ if item_id not in fake_db:
+ raise HTTPException(status_code=404, detail="Item not found")
+ return fake_db[item_id]
+
+
+@app.post("/items/", response_model=Item)
+async def create_item(item: Item, x_token: Annotated[str, Header()]):
+ if x_token != fake_secret_token:
+ raise HTTPException(status_code=400, detail="Invalid X-Token header")
+ if item.id in fake_db:
+ raise HTTPException(status_code=400, detail="Item already exists")
+ fake_db[item.id] = item
+ return item
diff --git a/docs_src/app_testing/app_b_an/test_main.py b/docs_src/app_testing/app_b_an/test_main.py
new file mode 100644
index 000000000..d186b8ecb
--- /dev/null
+++ b/docs_src/app_testing/app_b_an/test_main.py
@@ -0,0 +1,65 @@
+from fastapi.testclient import TestClient
+
+from .main import app
+
+client = TestClient(app)
+
+
+def test_read_item():
+ response = client.get("/items/foo", headers={"X-Token": "coneofsilence"})
+ assert response.status_code == 200
+ assert response.json() == {
+ "id": "foo",
+ "title": "Foo",
+ "description": "There goes my hero",
+ }
+
+
+def test_read_item_bad_token():
+ response = client.get("/items/foo", headers={"X-Token": "hailhydra"})
+ assert response.status_code == 400
+ assert response.json() == {"detail": "Invalid X-Token header"}
+
+
+def test_read_inexistent_item():
+ response = client.get("/items/baz", headers={"X-Token": "coneofsilence"})
+ assert response.status_code == 404
+ assert response.json() == {"detail": "Item not found"}
+
+
+def test_create_item():
+ response = client.post(
+ "/items/",
+ headers={"X-Token": "coneofsilence"},
+ json={"id": "foobar", "title": "Foo Bar", "description": "The Foo Barters"},
+ )
+ assert response.status_code == 200
+ assert response.json() == {
+ "id": "foobar",
+ "title": "Foo Bar",
+ "description": "The Foo Barters",
+ }
+
+
+def test_create_item_bad_token():
+ response = client.post(
+ "/items/",
+ headers={"X-Token": "hailhydra"},
+ json={"id": "bazz", "title": "Bazz", "description": "Drop the bazz"},
+ )
+ assert response.status_code == 400
+ assert response.json() == {"detail": "Invalid X-Token header"}
+
+
+def test_create_existing_item():
+ response = client.post(
+ "/items/",
+ headers={"X-Token": "coneofsilence"},
+ json={
+ "id": "foo",
+ "title": "The Foo ID Stealers",
+ "description": "There goes my stealer",
+ },
+ )
+ assert response.status_code == 400
+ assert response.json() == {"detail": "Item already exists"}
diff --git a/docs_src/app_testing/app_b_an_py310/__init__.py b/docs_src/app_testing/app_b_an_py310/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs_src/app_testing/app_b_an_py310/main.py b/docs_src/app_testing/app_b_an_py310/main.py
new file mode 100644
index 000000000..48c27a0b8
--- /dev/null
+++ b/docs_src/app_testing/app_b_an_py310/main.py
@@ -0,0 +1,38 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Header, HTTPException
+from pydantic import BaseModel
+
+fake_secret_token = "coneofsilence"
+
+fake_db = {
+ "foo": {"id": "foo", "title": "Foo", "description": "There goes my hero"},
+ "bar": {"id": "bar", "title": "Bar", "description": "The bartenders"},
+}
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ id: str
+ title: str
+ description: str | None = None
+
+
+@app.get("/items/{item_id}", response_model=Item)
+async def read_main(item_id: str, x_token: Annotated[str, Header()]):
+ if x_token != fake_secret_token:
+ raise HTTPException(status_code=400, detail="Invalid X-Token header")
+ if item_id not in fake_db:
+ raise HTTPException(status_code=404, detail="Item not found")
+ return fake_db[item_id]
+
+
+@app.post("/items/", response_model=Item)
+async def create_item(item: Item, x_token: Annotated[str, Header()]):
+ if x_token != fake_secret_token:
+ raise HTTPException(status_code=400, detail="Invalid X-Token header")
+ if item.id in fake_db:
+ raise HTTPException(status_code=400, detail="Item already exists")
+ fake_db[item.id] = item
+ return item
diff --git a/docs_src/app_testing/app_b_an_py310/test_main.py b/docs_src/app_testing/app_b_an_py310/test_main.py
new file mode 100644
index 000000000..d186b8ecb
--- /dev/null
+++ b/docs_src/app_testing/app_b_an_py310/test_main.py
@@ -0,0 +1,65 @@
+from fastapi.testclient import TestClient
+
+from .main import app
+
+client = TestClient(app)
+
+
+def test_read_item():
+ response = client.get("/items/foo", headers={"X-Token": "coneofsilence"})
+ assert response.status_code == 200
+ assert response.json() == {
+ "id": "foo",
+ "title": "Foo",
+ "description": "There goes my hero",
+ }
+
+
+def test_read_item_bad_token():
+ response = client.get("/items/foo", headers={"X-Token": "hailhydra"})
+ assert response.status_code == 400
+ assert response.json() == {"detail": "Invalid X-Token header"}
+
+
+def test_read_inexistent_item():
+ response = client.get("/items/baz", headers={"X-Token": "coneofsilence"})
+ assert response.status_code == 404
+ assert response.json() == {"detail": "Item not found"}
+
+
+def test_create_item():
+ response = client.post(
+ "/items/",
+ headers={"X-Token": "coneofsilence"},
+ json={"id": "foobar", "title": "Foo Bar", "description": "The Foo Barters"},
+ )
+ assert response.status_code == 200
+ assert response.json() == {
+ "id": "foobar",
+ "title": "Foo Bar",
+ "description": "The Foo Barters",
+ }
+
+
+def test_create_item_bad_token():
+ response = client.post(
+ "/items/",
+ headers={"X-Token": "hailhydra"},
+ json={"id": "bazz", "title": "Bazz", "description": "Drop the bazz"},
+ )
+ assert response.status_code == 400
+ assert response.json() == {"detail": "Invalid X-Token header"}
+
+
+def test_create_existing_item():
+ response = client.post(
+ "/items/",
+ headers={"X-Token": "coneofsilence"},
+ json={
+ "id": "foo",
+ "title": "The Foo ID Stealers",
+ "description": "There goes my stealer",
+ },
+ )
+ assert response.status_code == 400
+ assert response.json() == {"detail": "Item already exists"}
diff --git a/docs_src/app_testing/app_b_an_py39/__init__.py b/docs_src/app_testing/app_b_an_py39/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs_src/app_testing/app_b_an_py39/main.py b/docs_src/app_testing/app_b_an_py39/main.py
new file mode 100644
index 000000000..935a510b7
--- /dev/null
+++ b/docs_src/app_testing/app_b_an_py39/main.py
@@ -0,0 +1,38 @@
+from typing import Annotated, Union
+
+from fastapi import FastAPI, Header, HTTPException
+from pydantic import BaseModel
+
+fake_secret_token = "coneofsilence"
+
+fake_db = {
+ "foo": {"id": "foo", "title": "Foo", "description": "There goes my hero"},
+ "bar": {"id": "bar", "title": "Bar", "description": "The bartenders"},
+}
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ id: str
+ title: str
+ description: Union[str, None] = None
+
+
+@app.get("/items/{item_id}", response_model=Item)
+async def read_main(item_id: str, x_token: Annotated[str, Header()]):
+ if x_token != fake_secret_token:
+ raise HTTPException(status_code=400, detail="Invalid X-Token header")
+ if item_id not in fake_db:
+ raise HTTPException(status_code=404, detail="Item not found")
+ return fake_db[item_id]
+
+
+@app.post("/items/", response_model=Item)
+async def create_item(item: Item, x_token: Annotated[str, Header()]):
+ if x_token != fake_secret_token:
+ raise HTTPException(status_code=400, detail="Invalid X-Token header")
+ if item.id in fake_db:
+ raise HTTPException(status_code=400, detail="Item already exists")
+ fake_db[item.id] = item
+ return item
diff --git a/docs_src/app_testing/app_b_an_py39/test_main.py b/docs_src/app_testing/app_b_an_py39/test_main.py
new file mode 100644
index 000000000..d186b8ecb
--- /dev/null
+++ b/docs_src/app_testing/app_b_an_py39/test_main.py
@@ -0,0 +1,65 @@
+from fastapi.testclient import TestClient
+
+from .main import app
+
+client = TestClient(app)
+
+
+def test_read_item():
+ response = client.get("/items/foo", headers={"X-Token": "coneofsilence"})
+ assert response.status_code == 200
+ assert response.json() == {
+ "id": "foo",
+ "title": "Foo",
+ "description": "There goes my hero",
+ }
+
+
+def test_read_item_bad_token():
+ response = client.get("/items/foo", headers={"X-Token": "hailhydra"})
+ assert response.status_code == 400
+ assert response.json() == {"detail": "Invalid X-Token header"}
+
+
+def test_read_inexistent_item():
+ response = client.get("/items/baz", headers={"X-Token": "coneofsilence"})
+ assert response.status_code == 404
+ assert response.json() == {"detail": "Item not found"}
+
+
+def test_create_item():
+ response = client.post(
+ "/items/",
+ headers={"X-Token": "coneofsilence"},
+ json={"id": "foobar", "title": "Foo Bar", "description": "The Foo Barters"},
+ )
+ assert response.status_code == 200
+ assert response.json() == {
+ "id": "foobar",
+ "title": "Foo Bar",
+ "description": "The Foo Barters",
+ }
+
+
+def test_create_item_bad_token():
+ response = client.post(
+ "/items/",
+ headers={"X-Token": "hailhydra"},
+ json={"id": "bazz", "title": "Bazz", "description": "Drop the bazz"},
+ )
+ assert response.status_code == 400
+ assert response.json() == {"detail": "Invalid X-Token header"}
+
+
+def test_create_existing_item():
+ response = client.post(
+ "/items/",
+ headers={"X-Token": "coneofsilence"},
+ json={
+ "id": "foo",
+ "title": "The Foo ID Stealers",
+ "description": "There goes my stealer",
+ },
+ )
+ assert response.status_code == 400
+ assert response.json() == {"detail": "Item already exists"}
diff --git a/docs_src/background_tasks/tutorial002_an.py b/docs_src/background_tasks/tutorial002_an.py
new file mode 100644
index 000000000..f63502b09
--- /dev/null
+++ b/docs_src/background_tasks/tutorial002_an.py
@@ -0,0 +1,27 @@
+from typing import Union
+
+from fastapi import BackgroundTasks, Depends, FastAPI
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+def write_log(message: str):
+ with open("log.txt", mode="a") as log:
+ log.write(message)
+
+
+def get_query(background_tasks: BackgroundTasks, q: Union[str, None] = None):
+ if q:
+ message = f"found query: {q}\n"
+ background_tasks.add_task(write_log, message)
+ return q
+
+
+@app.post("/send-notification/{email}")
+async def send_notification(
+ email: str, background_tasks: BackgroundTasks, q: Annotated[str, Depends(get_query)]
+):
+ message = f"message to {email}\n"
+ background_tasks.add_task(write_log, message)
+ return {"message": "Message sent"}
diff --git a/docs_src/background_tasks/tutorial002_an_py310.py b/docs_src/background_tasks/tutorial002_an_py310.py
new file mode 100644
index 000000000..1fc78fbc9
--- /dev/null
+++ b/docs_src/background_tasks/tutorial002_an_py310.py
@@ -0,0 +1,26 @@
+from typing import Annotated
+
+from fastapi import BackgroundTasks, Depends, FastAPI
+
+app = FastAPI()
+
+
+def write_log(message: str):
+ with open("log.txt", mode="a") as log:
+ log.write(message)
+
+
+def get_query(background_tasks: BackgroundTasks, q: str | None = None):
+ if q:
+ message = f"found query: {q}\n"
+ background_tasks.add_task(write_log, message)
+ return q
+
+
+@app.post("/send-notification/{email}")
+async def send_notification(
+ email: str, background_tasks: BackgroundTasks, q: Annotated[str, Depends(get_query)]
+):
+ message = f"message to {email}\n"
+ background_tasks.add_task(write_log, message)
+ return {"message": "Message sent"}
diff --git a/docs_src/background_tasks/tutorial002_an_py39.py b/docs_src/background_tasks/tutorial002_an_py39.py
new file mode 100644
index 000000000..bfdd14875
--- /dev/null
+++ b/docs_src/background_tasks/tutorial002_an_py39.py
@@ -0,0 +1,26 @@
+from typing import Annotated, Union
+
+from fastapi import BackgroundTasks, Depends, FastAPI
+
+app = FastAPI()
+
+
+def write_log(message: str):
+ with open("log.txt", mode="a") as log:
+ log.write(message)
+
+
+def get_query(background_tasks: BackgroundTasks, q: Union[str, None] = None):
+ if q:
+ message = f"found query: {q}\n"
+ background_tasks.add_task(write_log, message)
+ return q
+
+
+@app.post("/send-notification/{email}")
+async def send_notification(
+ email: str, background_tasks: BackgroundTasks, q: Annotated[str, Depends(get_query)]
+):
+ message = f"message to {email}\n"
+ background_tasks.add_task(write_log, message)
+ return {"message": "Message sent"}
diff --git a/docs_src/bigger_applications/app_an/__init__.py b/docs_src/bigger_applications/app_an/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs_src/bigger_applications/app_an/dependencies.py b/docs_src/bigger_applications/app_an/dependencies.py
new file mode 100644
index 000000000..1374c54b3
--- /dev/null
+++ b/docs_src/bigger_applications/app_an/dependencies.py
@@ -0,0 +1,12 @@
+from fastapi import Header, HTTPException
+from typing_extensions import Annotated
+
+
+async def get_token_header(x_token: Annotated[str, Header()]):
+ if x_token != "fake-super-secret-token":
+ raise HTTPException(status_code=400, detail="X-Token header invalid")
+
+
+async def get_query_token(token: str):
+ if token != "jessica":
+ raise HTTPException(status_code=400, detail="No Jessica token provided")
diff --git a/docs_src/bigger_applications/app_an/internal/__init__.py b/docs_src/bigger_applications/app_an/internal/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs_src/bigger_applications/app_an/internal/admin.py b/docs_src/bigger_applications/app_an/internal/admin.py
new file mode 100644
index 000000000..99d3da86b
--- /dev/null
+++ b/docs_src/bigger_applications/app_an/internal/admin.py
@@ -0,0 +1,8 @@
+from fastapi import APIRouter
+
+router = APIRouter()
+
+
+@router.post("/")
+async def update_admin():
+ return {"message": "Admin getting schwifty"}
diff --git a/docs_src/bigger_applications/app_an/main.py b/docs_src/bigger_applications/app_an/main.py
new file mode 100644
index 000000000..ae544a3aa
--- /dev/null
+++ b/docs_src/bigger_applications/app_an/main.py
@@ -0,0 +1,23 @@
+from fastapi import Depends, FastAPI
+
+from .dependencies import get_query_token, get_token_header
+from .internal import admin
+from .routers import items, users
+
+app = FastAPI(dependencies=[Depends(get_query_token)])
+
+
+app.include_router(users.router)
+app.include_router(items.router)
+app.include_router(
+ admin.router,
+ prefix="/admin",
+ tags=["admin"],
+ dependencies=[Depends(get_token_header)],
+ responses={418: {"description": "I'm a teapot"}},
+)
+
+
+@app.get("/")
+async def root():
+ return {"message": "Hello Bigger Applications!"}
diff --git a/docs_src/bigger_applications/app_an/routers/__init__.py b/docs_src/bigger_applications/app_an/routers/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs_src/bigger_applications/app_an/routers/items.py b/docs_src/bigger_applications/app_an/routers/items.py
new file mode 100644
index 000000000..bde9ff4d5
--- /dev/null
+++ b/docs_src/bigger_applications/app_an/routers/items.py
@@ -0,0 +1,38 @@
+from fastapi import APIRouter, Depends, HTTPException
+
+from ..dependencies import get_token_header
+
+router = APIRouter(
+ prefix="/items",
+ tags=["items"],
+ dependencies=[Depends(get_token_header)],
+ responses={404: {"description": "Not found"}},
+)
+
+
+fake_items_db = {"plumbus": {"name": "Plumbus"}, "gun": {"name": "Portal Gun"}}
+
+
+@router.get("/")
+async def read_items():
+ return fake_items_db
+
+
+@router.get("/{item_id}")
+async def read_item(item_id: str):
+ if item_id not in fake_items_db:
+ raise HTTPException(status_code=404, detail="Item not found")
+ return {"name": fake_items_db[item_id]["name"], "item_id": item_id}
+
+
+@router.put(
+ "/{item_id}",
+ tags=["custom"],
+ responses={403: {"description": "Operation forbidden"}},
+)
+async def update_item(item_id: str):
+ if item_id != "plumbus":
+ raise HTTPException(
+ status_code=403, detail="You can only update the item: plumbus"
+ )
+ return {"item_id": item_id, "name": "The great Plumbus"}
diff --git a/docs_src/bigger_applications/app_an/routers/users.py b/docs_src/bigger_applications/app_an/routers/users.py
new file mode 100644
index 000000000..39b3d7e7c
--- /dev/null
+++ b/docs_src/bigger_applications/app_an/routers/users.py
@@ -0,0 +1,18 @@
+from fastapi import APIRouter
+
+router = APIRouter()
+
+
+@router.get("/users/", tags=["users"])
+async def read_users():
+ return [{"username": "Rick"}, {"username": "Morty"}]
+
+
+@router.get("/users/me", tags=["users"])
+async def read_user_me():
+ return {"username": "fakecurrentuser"}
+
+
+@router.get("/users/{username}", tags=["users"])
+async def read_user(username: str):
+ return {"username": username}
diff --git a/docs_src/bigger_applications/app_an_py39/__init__.py b/docs_src/bigger_applications/app_an_py39/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs_src/bigger_applications/app_an_py39/dependencies.py b/docs_src/bigger_applications/app_an_py39/dependencies.py
new file mode 100644
index 000000000..5c7612aa0
--- /dev/null
+++ b/docs_src/bigger_applications/app_an_py39/dependencies.py
@@ -0,0 +1,13 @@
+from typing import Annotated
+
+from fastapi import Header, HTTPException
+
+
+async def get_token_header(x_token: Annotated[str, Header()]):
+ if x_token != "fake-super-secret-token":
+ raise HTTPException(status_code=400, detail="X-Token header invalid")
+
+
+async def get_query_token(token: str):
+ if token != "jessica":
+ raise HTTPException(status_code=400, detail="No Jessica token provided")
diff --git a/docs_src/bigger_applications/app_an_py39/internal/__init__.py b/docs_src/bigger_applications/app_an_py39/internal/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs_src/bigger_applications/app_an_py39/internal/admin.py b/docs_src/bigger_applications/app_an_py39/internal/admin.py
new file mode 100644
index 000000000..99d3da86b
--- /dev/null
+++ b/docs_src/bigger_applications/app_an_py39/internal/admin.py
@@ -0,0 +1,8 @@
+from fastapi import APIRouter
+
+router = APIRouter()
+
+
+@router.post("/")
+async def update_admin():
+ return {"message": "Admin getting schwifty"}
diff --git a/docs_src/bigger_applications/app_an_py39/main.py b/docs_src/bigger_applications/app_an_py39/main.py
new file mode 100644
index 000000000..ae544a3aa
--- /dev/null
+++ b/docs_src/bigger_applications/app_an_py39/main.py
@@ -0,0 +1,23 @@
+from fastapi import Depends, FastAPI
+
+from .dependencies import get_query_token, get_token_header
+from .internal import admin
+from .routers import items, users
+
+app = FastAPI(dependencies=[Depends(get_query_token)])
+
+
+app.include_router(users.router)
+app.include_router(items.router)
+app.include_router(
+ admin.router,
+ prefix="/admin",
+ tags=["admin"],
+ dependencies=[Depends(get_token_header)],
+ responses={418: {"description": "I'm a teapot"}},
+)
+
+
+@app.get("/")
+async def root():
+ return {"message": "Hello Bigger Applications!"}
diff --git a/docs_src/bigger_applications/app_an_py39/routers/__init__.py b/docs_src/bigger_applications/app_an_py39/routers/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs_src/bigger_applications/app_an_py39/routers/items.py b/docs_src/bigger_applications/app_an_py39/routers/items.py
new file mode 100644
index 000000000..bde9ff4d5
--- /dev/null
+++ b/docs_src/bigger_applications/app_an_py39/routers/items.py
@@ -0,0 +1,38 @@
+from fastapi import APIRouter, Depends, HTTPException
+
+from ..dependencies import get_token_header
+
+router = APIRouter(
+ prefix="/items",
+ tags=["items"],
+ dependencies=[Depends(get_token_header)],
+ responses={404: {"description": "Not found"}},
+)
+
+
+fake_items_db = {"plumbus": {"name": "Plumbus"}, "gun": {"name": "Portal Gun"}}
+
+
+@router.get("/")
+async def read_items():
+ return fake_items_db
+
+
+@router.get("/{item_id}")
+async def read_item(item_id: str):
+ if item_id not in fake_items_db:
+ raise HTTPException(status_code=404, detail="Item not found")
+ return {"name": fake_items_db[item_id]["name"], "item_id": item_id}
+
+
+@router.put(
+ "/{item_id}",
+ tags=["custom"],
+ responses={403: {"description": "Operation forbidden"}},
+)
+async def update_item(item_id: str):
+ if item_id != "plumbus":
+ raise HTTPException(
+ status_code=403, detail="You can only update the item: plumbus"
+ )
+ return {"item_id": item_id, "name": "The great Plumbus"}
diff --git a/docs_src/bigger_applications/app_an_py39/routers/users.py b/docs_src/bigger_applications/app_an_py39/routers/users.py
new file mode 100644
index 000000000..39b3d7e7c
--- /dev/null
+++ b/docs_src/bigger_applications/app_an_py39/routers/users.py
@@ -0,0 +1,18 @@
+from fastapi import APIRouter
+
+router = APIRouter()
+
+
+@router.get("/users/", tags=["users"])
+async def read_users():
+ return [{"username": "Rick"}, {"username": "Morty"}]
+
+
+@router.get("/users/me", tags=["users"])
+async def read_user_me():
+ return {"username": "fakecurrentuser"}
+
+
+@router.get("/users/{username}", tags=["users"])
+async def read_user(username: str):
+ return {"username": username}
diff --git a/docs_src/body_fields/tutorial001_an.py b/docs_src/body_fields/tutorial001_an.py
new file mode 100644
index 000000000..15ea1b53d
--- /dev/null
+++ b/docs_src/body_fields/tutorial001_an.py
@@ -0,0 +1,22 @@
+from typing import Union
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel, Field
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: Union[str, None] = Field(
+ default=None, title="The description of the item", max_length=300
+ )
+ price: float = Field(gt=0, description="The price must be greater than zero")
+ tax: Union[float, None] = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs_src/body_fields/tutorial001_an_py310.py b/docs_src/body_fields/tutorial001_an_py310.py
new file mode 100644
index 000000000..c9d99e1c2
--- /dev/null
+++ b/docs_src/body_fields/tutorial001_an_py310.py
@@ -0,0 +1,21 @@
+from typing import Annotated
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel, Field
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: str | None = Field(
+ default=None, title="The description of the item", max_length=300
+ )
+ price: float = Field(gt=0, description="The price must be greater than zero")
+ tax: float | None = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs_src/body_fields/tutorial001_an_py39.py b/docs_src/body_fields/tutorial001_an_py39.py
new file mode 100644
index 000000000..6ef14470c
--- /dev/null
+++ b/docs_src/body_fields/tutorial001_an_py39.py
@@ -0,0 +1,21 @@
+from typing import Annotated, Union
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel, Field
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: Union[str, None] = Field(
+ default=None, title="The description of the item", max_length=300
+ )
+ price: float = Field(gt=0, description="The price must be greater than zero")
+ tax: Union[float, None] = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs_src/body_multiple_params/tutorial001_an.py b/docs_src/body_multiple_params/tutorial001_an.py
new file mode 100644
index 000000000..308eee854
--- /dev/null
+++ b/docs_src/body_multiple_params/tutorial001_an.py
@@ -0,0 +1,28 @@
+from typing import Union
+
+from fastapi import FastAPI, Path
+from pydantic import BaseModel
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: Union[str, None] = None
+ price: float
+ tax: Union[float, None] = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(
+ item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],
+ q: Union[str, None] = None,
+ item: Union[Item, None] = None,
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ if item:
+ results.update({"item": item})
+ return results
diff --git a/docs_src/body_multiple_params/tutorial001_an_py310.py b/docs_src/body_multiple_params/tutorial001_an_py310.py
new file mode 100644
index 000000000..2d79c19c2
--- /dev/null
+++ b/docs_src/body_multiple_params/tutorial001_an_py310.py
@@ -0,0 +1,27 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Path
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: str | None = None
+ price: float
+ tax: float | None = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(
+ item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],
+ q: str | None = None,
+ item: Item | None = None,
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ if item:
+ results.update({"item": item})
+ return results
diff --git a/docs_src/body_multiple_params/tutorial001_an_py39.py b/docs_src/body_multiple_params/tutorial001_an_py39.py
new file mode 100644
index 000000000..1c0ac3a7b
--- /dev/null
+++ b/docs_src/body_multiple_params/tutorial001_an_py39.py
@@ -0,0 +1,27 @@
+from typing import Annotated, Union
+
+from fastapi import FastAPI, Path
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: Union[str, None] = None
+ price: float
+ tax: Union[float, None] = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(
+ item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],
+ q: Union[str, None] = None,
+ item: Union[Item, None] = None,
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ if item:
+ results.update({"item": item})
+ return results
diff --git a/docs_src/body_multiple_params/tutorial003_an.py b/docs_src/body_multiple_params/tutorial003_an.py
new file mode 100644
index 000000000..39ef7340a
--- /dev/null
+++ b/docs_src/body_multiple_params/tutorial003_an.py
@@ -0,0 +1,27 @@
+from typing import Union
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: Union[str, None] = None
+ price: float
+ tax: Union[float, None] = None
+
+
+class User(BaseModel):
+ username: str
+ full_name: Union[str, None] = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(
+ item_id: int, item: Item, user: User, importance: Annotated[int, Body()]
+):
+ results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
+ return results
diff --git a/docs_src/body_multiple_params/tutorial003_an_py310.py b/docs_src/body_multiple_params/tutorial003_an_py310.py
new file mode 100644
index 000000000..593ff893c
--- /dev/null
+++ b/docs_src/body_multiple_params/tutorial003_an_py310.py
@@ -0,0 +1,26 @@
+from typing import Annotated
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: str | None = None
+ price: float
+ tax: float | None = None
+
+
+class User(BaseModel):
+ username: str
+ full_name: str | None = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(
+ item_id: int, item: Item, user: User, importance: Annotated[int, Body()]
+):
+ results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
+ return results
diff --git a/docs_src/body_multiple_params/tutorial003_an_py39.py b/docs_src/body_multiple_params/tutorial003_an_py39.py
new file mode 100644
index 000000000..042351e0b
--- /dev/null
+++ b/docs_src/body_multiple_params/tutorial003_an_py39.py
@@ -0,0 +1,26 @@
+from typing import Annotated, Union
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: Union[str, None] = None
+ price: float
+ tax: Union[float, None] = None
+
+
+class User(BaseModel):
+ username: str
+ full_name: Union[str, None] = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(
+ item_id: int, item: Item, user: User, importance: Annotated[int, Body()]
+):
+ results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
+ return results
diff --git a/docs_src/body_multiple_params/tutorial004_an.py b/docs_src/body_multiple_params/tutorial004_an.py
new file mode 100644
index 000000000..f6830f392
--- /dev/null
+++ b/docs_src/body_multiple_params/tutorial004_an.py
@@ -0,0 +1,34 @@
+from typing import Union
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: Union[str, None] = None
+ price: float
+ tax: Union[float, None] = None
+
+
+class User(BaseModel):
+ username: str
+ full_name: Union[str, None] = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(
+ *,
+ item_id: int,
+ item: Item,
+ user: User,
+ importance: Annotated[int, Body(gt=0)],
+ q: Union[str, None] = None,
+):
+ results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/body_multiple_params/tutorial004_an_py310.py b/docs_src/body_multiple_params/tutorial004_an_py310.py
new file mode 100644
index 000000000..cd5c66fef
--- /dev/null
+++ b/docs_src/body_multiple_params/tutorial004_an_py310.py
@@ -0,0 +1,33 @@
+from typing import Annotated
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: str | None = None
+ price: float
+ tax: float | None = None
+
+
+class User(BaseModel):
+ username: str
+ full_name: str | None = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(
+ *,
+ item_id: int,
+ item: Item,
+ user: User,
+ importance: Annotated[int, Body(gt=0)],
+ q: str | None = None,
+):
+ results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/body_multiple_params/tutorial004_an_py39.py b/docs_src/body_multiple_params/tutorial004_an_py39.py
new file mode 100644
index 000000000..567427c03
--- /dev/null
+++ b/docs_src/body_multiple_params/tutorial004_an_py39.py
@@ -0,0 +1,33 @@
+from typing import Annotated, Union
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: Union[str, None] = None
+ price: float
+ tax: Union[float, None] = None
+
+
+class User(BaseModel):
+ username: str
+ full_name: Union[str, None] = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(
+ *,
+ item_id: int,
+ item: Item,
+ user: User,
+ importance: Annotated[int, Body(gt=0)],
+ q: Union[str, None] = None,
+):
+ results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/body_multiple_params/tutorial005_an.py b/docs_src/body_multiple_params/tutorial005_an.py
new file mode 100644
index 000000000..dadde80b5
--- /dev/null
+++ b/docs_src/body_multiple_params/tutorial005_an.py
@@ -0,0 +1,20 @@
+from typing import Union
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: Union[str, None] = None
+ price: float
+ tax: Union[float, None] = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs_src/body_multiple_params/tutorial005_an_py310.py b/docs_src/body_multiple_params/tutorial005_an_py310.py
new file mode 100644
index 000000000..f97680ba0
--- /dev/null
+++ b/docs_src/body_multiple_params/tutorial005_an_py310.py
@@ -0,0 +1,19 @@
+from typing import Annotated
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: str | None = None
+ price: float
+ tax: float | None = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs_src/body_multiple_params/tutorial005_an_py39.py b/docs_src/body_multiple_params/tutorial005_an_py39.py
new file mode 100644
index 000000000..9a52425c1
--- /dev/null
+++ b/docs_src/body_multiple_params/tutorial005_an_py39.py
@@ -0,0 +1,19 @@
+from typing import Annotated, Union
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: Union[str, None] = None
+ price: float
+ tax: Union[float, None] = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs_src/cookie_params/tutorial001_an.py b/docs_src/cookie_params/tutorial001_an.py
new file mode 100644
index 000000000..6d5931229
--- /dev/null
+++ b/docs_src/cookie_params/tutorial001_an.py
@@ -0,0 +1,11 @@
+from typing import Union
+
+from fastapi import Cookie, FastAPI
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(ads_id: Annotated[Union[str, None], Cookie()] = None):
+ return {"ads_id": ads_id}
diff --git a/docs_src/cookie_params/tutorial001_an_py310.py b/docs_src/cookie_params/tutorial001_an_py310.py
new file mode 100644
index 000000000..69ac683fe
--- /dev/null
+++ b/docs_src/cookie_params/tutorial001_an_py310.py
@@ -0,0 +1,10 @@
+from typing import Annotated
+
+from fastapi import Cookie, FastAPI
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(ads_id: Annotated[str | None, Cookie()] = None):
+ return {"ads_id": ads_id}
diff --git a/docs_src/cookie_params/tutorial001_an_py39.py b/docs_src/cookie_params/tutorial001_an_py39.py
new file mode 100644
index 000000000..e18d0a332
--- /dev/null
+++ b/docs_src/cookie_params/tutorial001_an_py39.py
@@ -0,0 +1,10 @@
+from typing import Annotated, Union
+
+from fastapi import Cookie, FastAPI
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(ads_id: Annotated[Union[str, None], Cookie()] = None):
+ return {"ads_id": ads_id}
diff --git a/docs_src/dependencies/tutorial001_02_an.py b/docs_src/dependencies/tutorial001_02_an.py
new file mode 100644
index 000000000..455d60c82
--- /dev/null
+++ b/docs_src/dependencies/tutorial001_02_an.py
@@ -0,0 +1,25 @@
+from typing import Union
+
+from fastapi import Depends, FastAPI
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+async def common_parameters(
+ q: Union[str, None] = None, skip: int = 0, limit: int = 100
+):
+ return {"q": q, "skip": skip, "limit": limit}
+
+
+CommonsDep = Annotated[dict, Depends(common_parameters)]
+
+
+@app.get("/items/")
+async def read_items(commons: CommonsDep):
+ return commons
+
+
+@app.get("/users/")
+async def read_users(commons: CommonsDep):
+ return commons
diff --git a/docs_src/dependencies/tutorial001_02_an_py310.py b/docs_src/dependencies/tutorial001_02_an_py310.py
new file mode 100644
index 000000000..f59637bb2
--- /dev/null
+++ b/docs_src/dependencies/tutorial001_02_an_py310.py
@@ -0,0 +1,22 @@
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+
+app = FastAPI()
+
+
+async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
+ return {"q": q, "skip": skip, "limit": limit}
+
+
+CommonsDep = Annotated[dict, Depends(common_parameters)]
+
+
+@app.get("/items/")
+async def read_items(commons: CommonsDep):
+ return commons
+
+
+@app.get("/users/")
+async def read_users(commons: CommonsDep):
+ return commons
diff --git a/docs_src/dependencies/tutorial001_02_an_py39.py b/docs_src/dependencies/tutorial001_02_an_py39.py
new file mode 100644
index 000000000..df969ae9c
--- /dev/null
+++ b/docs_src/dependencies/tutorial001_02_an_py39.py
@@ -0,0 +1,24 @@
+from typing import Annotated, Union
+
+from fastapi import Depends, FastAPI
+
+app = FastAPI()
+
+
+async def common_parameters(
+ q: Union[str, None] = None, skip: int = 0, limit: int = 100
+):
+ return {"q": q, "skip": skip, "limit": limit}
+
+
+CommonsDep = Annotated[dict, Depends(common_parameters)]
+
+
+@app.get("/items/")
+async def read_items(commons: CommonsDep):
+ return commons
+
+
+@app.get("/users/")
+async def read_users(commons: CommonsDep):
+ return commons
diff --git a/docs_src/dependencies/tutorial001_an.py b/docs_src/dependencies/tutorial001_an.py
new file mode 100644
index 000000000..81e24fe86
--- /dev/null
+++ b/docs_src/dependencies/tutorial001_an.py
@@ -0,0 +1,22 @@
+from typing import Union
+
+from fastapi import Depends, FastAPI
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+async def common_parameters(
+ q: Union[str, None] = None, skip: int = 0, limit: int = 100
+):
+ return {"q": q, "skip": skip, "limit": limit}
+
+
+@app.get("/items/")
+async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
+ return commons
+
+
+@app.get("/users/")
+async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
+ return commons
diff --git a/docs_src/dependencies/tutorial001_an_py310.py b/docs_src/dependencies/tutorial001_an_py310.py
new file mode 100644
index 000000000..f2e57ae7b
--- /dev/null
+++ b/docs_src/dependencies/tutorial001_an_py310.py
@@ -0,0 +1,19 @@
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+
+app = FastAPI()
+
+
+async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
+ return {"q": q, "skip": skip, "limit": limit}
+
+
+@app.get("/items/")
+async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
+ return commons
+
+
+@app.get("/users/")
+async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
+ return commons
diff --git a/docs_src/dependencies/tutorial001_an_py39.py b/docs_src/dependencies/tutorial001_an_py39.py
new file mode 100644
index 000000000..5d9fe6ddf
--- /dev/null
+++ b/docs_src/dependencies/tutorial001_an_py39.py
@@ -0,0 +1,21 @@
+from typing import Annotated, Union
+
+from fastapi import Depends, FastAPI
+
+app = FastAPI()
+
+
+async def common_parameters(
+ q: Union[str, None] = None, skip: int = 0, limit: int = 100
+):
+ return {"q": q, "skip": skip, "limit": limit}
+
+
+@app.get("/items/")
+async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
+ return commons
+
+
+@app.get("/users/")
+async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
+ return commons
diff --git a/docs_src/dependencies/tutorial002_an.py b/docs_src/dependencies/tutorial002_an.py
new file mode 100644
index 000000000..964ccf66c
--- /dev/null
+++ b/docs_src/dependencies/tutorial002_an.py
@@ -0,0 +1,26 @@
+from typing import Union
+
+from fastapi import Depends, FastAPI
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
+
+
+class CommonQueryParams:
+ def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
+ self.q = q
+ self.skip = skip
+ self.limit = limit
+
+
+@app.get("/items/")
+async def read_items(commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]):
+ response = {}
+ if commons.q:
+ response.update({"q": commons.q})
+ items = fake_items_db[commons.skip : commons.skip + commons.limit]
+ response.update({"items": items})
+ return response
diff --git a/docs_src/dependencies/tutorial002_an_py310.py b/docs_src/dependencies/tutorial002_an_py310.py
new file mode 100644
index 000000000..077726312
--- /dev/null
+++ b/docs_src/dependencies/tutorial002_an_py310.py
@@ -0,0 +1,25 @@
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+
+app = FastAPI()
+
+
+fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
+
+
+class CommonQueryParams:
+ def __init__(self, q: str | None = None, skip: int = 0, limit: int = 100):
+ self.q = q
+ self.skip = skip
+ self.limit = limit
+
+
+@app.get("/items/")
+async def read_items(commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]):
+ response = {}
+ if commons.q:
+ response.update({"q": commons.q})
+ items = fake_items_db[commons.skip : commons.skip + commons.limit]
+ response.update({"items": items})
+ return response
diff --git a/docs_src/dependencies/tutorial002_an_py39.py b/docs_src/dependencies/tutorial002_an_py39.py
new file mode 100644
index 000000000..844a23c5a
--- /dev/null
+++ b/docs_src/dependencies/tutorial002_an_py39.py
@@ -0,0 +1,25 @@
+from typing import Annotated, Union
+
+from fastapi import Depends, FastAPI
+
+app = FastAPI()
+
+
+fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
+
+
+class CommonQueryParams:
+ def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
+ self.q = q
+ self.skip = skip
+ self.limit = limit
+
+
+@app.get("/items/")
+async def read_items(commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]):
+ response = {}
+ if commons.q:
+ response.update({"q": commons.q})
+ items = fake_items_db[commons.skip : commons.skip + commons.limit]
+ response.update({"items": items})
+ return response
diff --git a/docs_src/dependencies/tutorial003_an.py b/docs_src/dependencies/tutorial003_an.py
new file mode 100644
index 000000000..ba8e9f717
--- /dev/null
+++ b/docs_src/dependencies/tutorial003_an.py
@@ -0,0 +1,26 @@
+from typing import Any, Union
+
+from fastapi import Depends, FastAPI
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
+
+
+class CommonQueryParams:
+ def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
+ self.q = q
+ self.skip = skip
+ self.limit = limit
+
+
+@app.get("/items/")
+async def read_items(commons: Annotated[Any, Depends(CommonQueryParams)]):
+ response = {}
+ if commons.q:
+ response.update({"q": commons.q})
+ items = fake_items_db[commons.skip : commons.skip + commons.limit]
+ response.update({"items": items})
+ return response
diff --git a/docs_src/dependencies/tutorial003_an_py310.py b/docs_src/dependencies/tutorial003_an_py310.py
new file mode 100644
index 000000000..44116989b
--- /dev/null
+++ b/docs_src/dependencies/tutorial003_an_py310.py
@@ -0,0 +1,25 @@
+from typing import Annotated, Any
+
+from fastapi import Depends, FastAPI
+
+app = FastAPI()
+
+
+fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
+
+
+class CommonQueryParams:
+ def __init__(self, q: str | None = None, skip: int = 0, limit: int = 100):
+ self.q = q
+ self.skip = skip
+ self.limit = limit
+
+
+@app.get("/items/")
+async def read_items(commons: Annotated[Any, Depends(CommonQueryParams)]):
+ response = {}
+ if commons.q:
+ response.update({"q": commons.q})
+ items = fake_items_db[commons.skip : commons.skip + commons.limit]
+ response.update({"items": items})
+ return response
diff --git a/docs_src/dependencies/tutorial003_an_py39.py b/docs_src/dependencies/tutorial003_an_py39.py
new file mode 100644
index 000000000..9e9123ad2
--- /dev/null
+++ b/docs_src/dependencies/tutorial003_an_py39.py
@@ -0,0 +1,25 @@
+from typing import Annotated, Any, Union
+
+from fastapi import Depends, FastAPI
+
+app = FastAPI()
+
+
+fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
+
+
+class CommonQueryParams:
+ def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
+ self.q = q
+ self.skip = skip
+ self.limit = limit
+
+
+@app.get("/items/")
+async def read_items(commons: Annotated[Any, Depends(CommonQueryParams)]):
+ response = {}
+ if commons.q:
+ response.update({"q": commons.q})
+ items = fake_items_db[commons.skip : commons.skip + commons.limit]
+ response.update({"items": items})
+ return response
diff --git a/docs_src/dependencies/tutorial004_an.py b/docs_src/dependencies/tutorial004_an.py
new file mode 100644
index 000000000..78881a354
--- /dev/null
+++ b/docs_src/dependencies/tutorial004_an.py
@@ -0,0 +1,26 @@
+from typing import Union
+
+from fastapi import Depends, FastAPI
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
+
+
+class CommonQueryParams:
+ def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
+ self.q = q
+ self.skip = skip
+ self.limit = limit
+
+
+@app.get("/items/")
+async def read_items(commons: Annotated[CommonQueryParams, Depends()]):
+ response = {}
+ if commons.q:
+ response.update({"q": commons.q})
+ items = fake_items_db[commons.skip : commons.skip + commons.limit]
+ response.update({"items": items})
+ return response
diff --git a/docs_src/dependencies/tutorial004_an_py310.py b/docs_src/dependencies/tutorial004_an_py310.py
new file mode 100644
index 000000000..2c009efcc
--- /dev/null
+++ b/docs_src/dependencies/tutorial004_an_py310.py
@@ -0,0 +1,25 @@
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+
+app = FastAPI()
+
+
+fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
+
+
+class CommonQueryParams:
+ def __init__(self, q: str | None = None, skip: int = 0, limit: int = 100):
+ self.q = q
+ self.skip = skip
+ self.limit = limit
+
+
+@app.get("/items/")
+async def read_items(commons: Annotated[CommonQueryParams, Depends()]):
+ response = {}
+ if commons.q:
+ response.update({"q": commons.q})
+ items = fake_items_db[commons.skip : commons.skip + commons.limit]
+ response.update({"items": items})
+ return response
diff --git a/docs_src/dependencies/tutorial004_an_py39.py b/docs_src/dependencies/tutorial004_an_py39.py
new file mode 100644
index 000000000..74268626b
--- /dev/null
+++ b/docs_src/dependencies/tutorial004_an_py39.py
@@ -0,0 +1,25 @@
+from typing import Annotated, Union
+
+from fastapi import Depends, FastAPI
+
+app = FastAPI()
+
+
+fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
+
+
+class CommonQueryParams:
+ def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
+ self.q = q
+ self.skip = skip
+ self.limit = limit
+
+
+@app.get("/items/")
+async def read_items(commons: Annotated[CommonQueryParams, Depends()]):
+ response = {}
+ if commons.q:
+ response.update({"q": commons.q})
+ items = fake_items_db[commons.skip : commons.skip + commons.limit]
+ response.update({"items": items})
+ return response
diff --git a/docs_src/dependencies/tutorial005_an.py b/docs_src/dependencies/tutorial005_an.py
new file mode 100644
index 000000000..6785099da
--- /dev/null
+++ b/docs_src/dependencies/tutorial005_an.py
@@ -0,0 +1,26 @@
+from typing import Union
+
+from fastapi import Cookie, Depends, FastAPI
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+def query_extractor(q: Union[str, None] = None):
+ return q
+
+
+def query_or_cookie_extractor(
+ q: Annotated[str, Depends(query_extractor)],
+ last_query: Annotated[Union[str, None], Cookie()] = None,
+):
+ if not q:
+ return last_query
+ return q
+
+
+@app.get("/items/")
+async def read_query(
+ query_or_default: Annotated[str, Depends(query_or_cookie_extractor)]
+):
+ return {"q_or_cookie": query_or_default}
diff --git a/docs_src/dependencies/tutorial005_an_py310.py b/docs_src/dependencies/tutorial005_an_py310.py
new file mode 100644
index 000000000..6c0aa0b36
--- /dev/null
+++ b/docs_src/dependencies/tutorial005_an_py310.py
@@ -0,0 +1,25 @@
+from typing import Annotated
+
+from fastapi import Cookie, Depends, FastAPI
+
+app = FastAPI()
+
+
+def query_extractor(q: str | None = None):
+ return q
+
+
+def query_or_cookie_extractor(
+ q: Annotated[str, Depends(query_extractor)],
+ last_query: Annotated[str | None, Cookie()] = None,
+):
+ if not q:
+ return last_query
+ return q
+
+
+@app.get("/items/")
+async def read_query(
+ query_or_default: Annotated[str, Depends(query_or_cookie_extractor)]
+):
+ return {"q_or_cookie": query_or_default}
diff --git a/docs_src/dependencies/tutorial005_an_py39.py b/docs_src/dependencies/tutorial005_an_py39.py
new file mode 100644
index 000000000..e8887e162
--- /dev/null
+++ b/docs_src/dependencies/tutorial005_an_py39.py
@@ -0,0 +1,25 @@
+from typing import Annotated, Union
+
+from fastapi import Cookie, Depends, FastAPI
+
+app = FastAPI()
+
+
+def query_extractor(q: Union[str, None] = None):
+ return q
+
+
+def query_or_cookie_extractor(
+ q: Annotated[str, Depends(query_extractor)],
+ last_query: Annotated[Union[str, None], Cookie()] = None,
+):
+ if not q:
+ return last_query
+ return q
+
+
+@app.get("/items/")
+async def read_query(
+ query_or_default: Annotated[str, Depends(query_or_cookie_extractor)]
+):
+ return {"q_or_cookie": query_or_default}
diff --git a/docs_src/dependencies/tutorial006_an.py b/docs_src/dependencies/tutorial006_an.py
new file mode 100644
index 000000000..5aaea04d1
--- /dev/null
+++ b/docs_src/dependencies/tutorial006_an.py
@@ -0,0 +1,20 @@
+from fastapi import Depends, FastAPI, Header, HTTPException
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+async def verify_token(x_token: Annotated[str, Header()]):
+ if x_token != "fake-super-secret-token":
+ raise HTTPException(status_code=400, detail="X-Token header invalid")
+
+
+async def verify_key(x_key: Annotated[str, Header()]):
+ if x_key != "fake-super-secret-key":
+ raise HTTPException(status_code=400, detail="X-Key header invalid")
+ return x_key
+
+
+@app.get("/items/", dependencies=[Depends(verify_token), Depends(verify_key)])
+async def read_items():
+ return [{"item": "Foo"}, {"item": "Bar"}]
diff --git a/docs_src/dependencies/tutorial006_an_py39.py b/docs_src/dependencies/tutorial006_an_py39.py
new file mode 100644
index 000000000..11976ed6a
--- /dev/null
+++ b/docs_src/dependencies/tutorial006_an_py39.py
@@ -0,0 +1,21 @@
+from typing import Annotated
+
+from fastapi import Depends, FastAPI, Header, HTTPException
+
+app = FastAPI()
+
+
+async def verify_token(x_token: Annotated[str, Header()]):
+ if x_token != "fake-super-secret-token":
+ raise HTTPException(status_code=400, detail="X-Token header invalid")
+
+
+async def verify_key(x_key: Annotated[str, Header()]):
+ if x_key != "fake-super-secret-key":
+ raise HTTPException(status_code=400, detail="X-Key header invalid")
+ return x_key
+
+
+@app.get("/items/", dependencies=[Depends(verify_token), Depends(verify_key)])
+async def read_items():
+ return [{"item": "Foo"}, {"item": "Bar"}]
diff --git a/docs_src/dependencies/tutorial008_an.py b/docs_src/dependencies/tutorial008_an.py
new file mode 100644
index 000000000..2de86f042
--- /dev/null
+++ b/docs_src/dependencies/tutorial008_an.py
@@ -0,0 +1,26 @@
+from fastapi import Depends
+from typing_extensions import Annotated
+
+
+async def dependency_a():
+ dep_a = generate_dep_a()
+ try:
+ yield dep_a
+ finally:
+ dep_a.close()
+
+
+async def dependency_b(dep_a: Annotated[DepA, Depends(dependency_a)]):
+ dep_b = generate_dep_b()
+ try:
+ yield dep_b
+ finally:
+ dep_b.close(dep_a)
+
+
+async def dependency_c(dep_b: Annotated[DepB, Depends(dependency_b)]):
+ dep_c = generate_dep_c()
+ try:
+ yield dep_c
+ finally:
+ dep_c.close(dep_b)
diff --git a/docs_src/dependencies/tutorial008_an_py39.py b/docs_src/dependencies/tutorial008_an_py39.py
new file mode 100644
index 000000000..acc804c32
--- /dev/null
+++ b/docs_src/dependencies/tutorial008_an_py39.py
@@ -0,0 +1,27 @@
+from typing import Annotated
+
+from fastapi import Depends
+
+
+async def dependency_a():
+ dep_a = generate_dep_a()
+ try:
+ yield dep_a
+ finally:
+ dep_a.close()
+
+
+async def dependency_b(dep_a: Annotated[DepA, Depends(dependency_a)]):
+ dep_b = generate_dep_b()
+ try:
+ yield dep_b
+ finally:
+ dep_b.close(dep_a)
+
+
+async def dependency_c(dep_b: Annotated[DepB, Depends(dependency_b)]):
+ dep_c = generate_dep_c()
+ try:
+ yield dep_c
+ finally:
+ dep_c.close(dep_b)
diff --git a/docs_src/dependencies/tutorial011_an.py b/docs_src/dependencies/tutorial011_an.py
new file mode 100644
index 000000000..6c13d9033
--- /dev/null
+++ b/docs_src/dependencies/tutorial011_an.py
@@ -0,0 +1,22 @@
+from fastapi import Depends, FastAPI
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+class FixedContentQueryChecker:
+ def __init__(self, fixed_content: str):
+ self.fixed_content = fixed_content
+
+ def __call__(self, q: str = ""):
+ if q:
+ return self.fixed_content in q
+ return False
+
+
+checker = FixedContentQueryChecker("bar")
+
+
+@app.get("/query-checker/")
+async def read_query_check(fixed_content_included: Annotated[bool, Depends(checker)]):
+ return {"fixed_content_in_query": fixed_content_included}
diff --git a/docs_src/dependencies/tutorial011_an_py39.py b/docs_src/dependencies/tutorial011_an_py39.py
new file mode 100644
index 000000000..68b7434ec
--- /dev/null
+++ b/docs_src/dependencies/tutorial011_an_py39.py
@@ -0,0 +1,23 @@
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+
+app = FastAPI()
+
+
+class FixedContentQueryChecker:
+ def __init__(self, fixed_content: str):
+ self.fixed_content = fixed_content
+
+ def __call__(self, q: str = ""):
+ if q:
+ return self.fixed_content in q
+ return False
+
+
+checker = FixedContentQueryChecker("bar")
+
+
+@app.get("/query-checker/")
+async def read_query_check(fixed_content_included: Annotated[bool, Depends(checker)]):
+ return {"fixed_content_in_query": fixed_content_included}
diff --git a/docs_src/dependencies/tutorial012_an.py b/docs_src/dependencies/tutorial012_an.py
new file mode 100644
index 000000000..7541e6bf4
--- /dev/null
+++ b/docs_src/dependencies/tutorial012_an.py
@@ -0,0 +1,26 @@
+from fastapi import Depends, FastAPI, Header, HTTPException
+from typing_extensions import Annotated
+
+
+async def verify_token(x_token: Annotated[str, Header()]):
+ if x_token != "fake-super-secret-token":
+ raise HTTPException(status_code=400, detail="X-Token header invalid")
+
+
+async def verify_key(x_key: Annotated[str, Header()]):
+ if x_key != "fake-super-secret-key":
+ raise HTTPException(status_code=400, detail="X-Key header invalid")
+ return x_key
+
+
+app = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)])
+
+
+@app.get("/items/")
+async def read_items():
+ return [{"item": "Portal Gun"}, {"item": "Plumbus"}]
+
+
+@app.get("/users/")
+async def read_users():
+ return [{"username": "Rick"}, {"username": "Morty"}]
diff --git a/docs_src/dependencies/tutorial012_an_py39.py b/docs_src/dependencies/tutorial012_an_py39.py
new file mode 100644
index 000000000..7541e6bf4
--- /dev/null
+++ b/docs_src/dependencies/tutorial012_an_py39.py
@@ -0,0 +1,26 @@
+from fastapi import Depends, FastAPI, Header, HTTPException
+from typing_extensions import Annotated
+
+
+async def verify_token(x_token: Annotated[str, Header()]):
+ if x_token != "fake-super-secret-token":
+ raise HTTPException(status_code=400, detail="X-Token header invalid")
+
+
+async def verify_key(x_key: Annotated[str, Header()]):
+ if x_key != "fake-super-secret-key":
+ raise HTTPException(status_code=400, detail="X-Key header invalid")
+ return x_key
+
+
+app = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)])
+
+
+@app.get("/items/")
+async def read_items():
+ return [{"item": "Portal Gun"}, {"item": "Plumbus"}]
+
+
+@app.get("/users/")
+async def read_users():
+ return [{"username": "Rick"}, {"username": "Morty"}]
diff --git a/docs_src/dependency_testing/tutorial001_an.py b/docs_src/dependency_testing/tutorial001_an.py
new file mode 100644
index 000000000..4c76a87ff
--- /dev/null
+++ b/docs_src/dependency_testing/tutorial001_an.py
@@ -0,0 +1,60 @@
+from typing import Union
+
+from fastapi import Depends, FastAPI
+from fastapi.testclient import TestClient
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+async def common_parameters(
+ q: Union[str, None] = None, skip: int = 0, limit: int = 100
+):
+ return {"q": q, "skip": skip, "limit": limit}
+
+
+@app.get("/items/")
+async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
+ return {"message": "Hello Items!", "params": commons}
+
+
+@app.get("/users/")
+async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
+ return {"message": "Hello Users!", "params": commons}
+
+
+client = TestClient(app)
+
+
+async def override_dependency(q: Union[str, None] = None):
+ return {"q": q, "skip": 5, "limit": 10}
+
+
+app.dependency_overrides[common_parameters] = override_dependency
+
+
+def test_override_in_items():
+ response = client.get("/items/")
+ assert response.status_code == 200
+ assert response.json() == {
+ "message": "Hello Items!",
+ "params": {"q": None, "skip": 5, "limit": 10},
+ }
+
+
+def test_override_in_items_with_q():
+ response = client.get("/items/?q=foo")
+ assert response.status_code == 200
+ assert response.json() == {
+ "message": "Hello Items!",
+ "params": {"q": "foo", "skip": 5, "limit": 10},
+ }
+
+
+def test_override_in_items_with_params():
+ response = client.get("/items/?q=foo&skip=100&limit=200")
+ assert response.status_code == 200
+ assert response.json() == {
+ "message": "Hello Items!",
+ "params": {"q": "foo", "skip": 5, "limit": 10},
+ }
diff --git a/docs_src/dependency_testing/tutorial001_an_py310.py b/docs_src/dependency_testing/tutorial001_an_py310.py
new file mode 100644
index 000000000..f866e7a1b
--- /dev/null
+++ b/docs_src/dependency_testing/tutorial001_an_py310.py
@@ -0,0 +1,57 @@
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+from fastapi.testclient import TestClient
+
+app = FastAPI()
+
+
+async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
+ return {"q": q, "skip": skip, "limit": limit}
+
+
+@app.get("/items/")
+async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
+ return {"message": "Hello Items!", "params": commons}
+
+
+@app.get("/users/")
+async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
+ return {"message": "Hello Users!", "params": commons}
+
+
+client = TestClient(app)
+
+
+async def override_dependency(q: str | None = None):
+ return {"q": q, "skip": 5, "limit": 10}
+
+
+app.dependency_overrides[common_parameters] = override_dependency
+
+
+def test_override_in_items():
+ response = client.get("/items/")
+ assert response.status_code == 200
+ assert response.json() == {
+ "message": "Hello Items!",
+ "params": {"q": None, "skip": 5, "limit": 10},
+ }
+
+
+def test_override_in_items_with_q():
+ response = client.get("/items/?q=foo")
+ assert response.status_code == 200
+ assert response.json() == {
+ "message": "Hello Items!",
+ "params": {"q": "foo", "skip": 5, "limit": 10},
+ }
+
+
+def test_override_in_items_with_params():
+ response = client.get("/items/?q=foo&skip=100&limit=200")
+ assert response.status_code == 200
+ assert response.json() == {
+ "message": "Hello Items!",
+ "params": {"q": "foo", "skip": 5, "limit": 10},
+ }
diff --git a/docs_src/dependency_testing/tutorial001_an_py39.py b/docs_src/dependency_testing/tutorial001_an_py39.py
new file mode 100644
index 000000000..bccb0cdb1
--- /dev/null
+++ b/docs_src/dependency_testing/tutorial001_an_py39.py
@@ -0,0 +1,59 @@
+from typing import Annotated, Union
+
+from fastapi import Depends, FastAPI
+from fastapi.testclient import TestClient
+
+app = FastAPI()
+
+
+async def common_parameters(
+ q: Union[str, None] = None, skip: int = 0, limit: int = 100
+):
+ return {"q": q, "skip": skip, "limit": limit}
+
+
+@app.get("/items/")
+async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
+ return {"message": "Hello Items!", "params": commons}
+
+
+@app.get("/users/")
+async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
+ return {"message": "Hello Users!", "params": commons}
+
+
+client = TestClient(app)
+
+
+async def override_dependency(q: Union[str, None] = None):
+ return {"q": q, "skip": 5, "limit": 10}
+
+
+app.dependency_overrides[common_parameters] = override_dependency
+
+
+def test_override_in_items():
+ response = client.get("/items/")
+ assert response.status_code == 200
+ assert response.json() == {
+ "message": "Hello Items!",
+ "params": {"q": None, "skip": 5, "limit": 10},
+ }
+
+
+def test_override_in_items_with_q():
+ response = client.get("/items/?q=foo")
+ assert response.status_code == 200
+ assert response.json() == {
+ "message": "Hello Items!",
+ "params": {"q": "foo", "skip": 5, "limit": 10},
+ }
+
+
+def test_override_in_items_with_params():
+ response = client.get("/items/?q=foo&skip=100&limit=200")
+ assert response.status_code == 200
+ assert response.json() == {
+ "message": "Hello Items!",
+ "params": {"q": "foo", "skip": 5, "limit": 10},
+ }
diff --git a/docs_src/dependency_testing/tutorial001_py310.py b/docs_src/dependency_testing/tutorial001_py310.py
new file mode 100644
index 000000000..d1f6d4374
--- /dev/null
+++ b/docs_src/dependency_testing/tutorial001_py310.py
@@ -0,0 +1,55 @@
+from fastapi import Depends, FastAPI
+from fastapi.testclient import TestClient
+
+app = FastAPI()
+
+
+async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
+ return {"q": q, "skip": skip, "limit": limit}
+
+
+@app.get("/items/")
+async def read_items(commons: dict = Depends(common_parameters)):
+ return {"message": "Hello Items!", "params": commons}
+
+
+@app.get("/users/")
+async def read_users(commons: dict = Depends(common_parameters)):
+ return {"message": "Hello Users!", "params": commons}
+
+
+client = TestClient(app)
+
+
+async def override_dependency(q: str | None = None):
+ return {"q": q, "skip": 5, "limit": 10}
+
+
+app.dependency_overrides[common_parameters] = override_dependency
+
+
+def test_override_in_items():
+ response = client.get("/items/")
+ assert response.status_code == 200
+ assert response.json() == {
+ "message": "Hello Items!",
+ "params": {"q": None, "skip": 5, "limit": 10},
+ }
+
+
+def test_override_in_items_with_q():
+ response = client.get("/items/?q=foo")
+ assert response.status_code == 200
+ assert response.json() == {
+ "message": "Hello Items!",
+ "params": {"q": "foo", "skip": 5, "limit": 10},
+ }
+
+
+def test_override_in_items_with_params():
+ response = client.get("/items/?q=foo&skip=100&limit=200")
+ assert response.status_code == 200
+ assert response.json() == {
+ "message": "Hello Items!",
+ "params": {"q": "foo", "skip": 5, "limit": 10},
+ }
diff --git a/docs_src/extra_data_types/tutorial001_an.py b/docs_src/extra_data_types/tutorial001_an.py
new file mode 100644
index 000000000..a4c074241
--- /dev/null
+++ b/docs_src/extra_data_types/tutorial001_an.py
@@ -0,0 +1,29 @@
+from datetime import datetime, time, timedelta
+from typing import Union
+from uuid import UUID
+
+from fastapi import Body, FastAPI
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.put("/items/{item_id}")
+async def read_items(
+ item_id: UUID,
+ start_datetime: Annotated[Union[datetime, None], Body()] = None,
+ end_datetime: Annotated[Union[datetime, None], Body()] = None,
+ repeat_at: Annotated[Union[time, None], Body()] = None,
+ process_after: Annotated[Union[timedelta, None], Body()] = None,
+):
+ start_process = start_datetime + process_after
+ duration = end_datetime - start_process
+ return {
+ "item_id": item_id,
+ "start_datetime": start_datetime,
+ "end_datetime": end_datetime,
+ "repeat_at": repeat_at,
+ "process_after": process_after,
+ "start_process": start_process,
+ "duration": duration,
+ }
diff --git a/docs_src/extra_data_types/tutorial001_an_py310.py b/docs_src/extra_data_types/tutorial001_an_py310.py
new file mode 100644
index 000000000..4f69c40d9
--- /dev/null
+++ b/docs_src/extra_data_types/tutorial001_an_py310.py
@@ -0,0 +1,28 @@
+from datetime import datetime, time, timedelta
+from typing import Annotated
+from uuid import UUID
+
+from fastapi import Body, FastAPI
+
+app = FastAPI()
+
+
+@app.put("/items/{item_id}")
+async def read_items(
+ item_id: UUID,
+ start_datetime: Annotated[datetime | None, Body()] = None,
+ end_datetime: Annotated[datetime | None, Body()] = None,
+ repeat_at: Annotated[time | None, Body()] = None,
+ process_after: Annotated[timedelta | None, Body()] = None,
+):
+ start_process = start_datetime + process_after
+ duration = end_datetime - start_process
+ return {
+ "item_id": item_id,
+ "start_datetime": start_datetime,
+ "end_datetime": end_datetime,
+ "repeat_at": repeat_at,
+ "process_after": process_after,
+ "start_process": start_process,
+ "duration": duration,
+ }
diff --git a/docs_src/extra_data_types/tutorial001_an_py39.py b/docs_src/extra_data_types/tutorial001_an_py39.py
new file mode 100644
index 000000000..630d36ae3
--- /dev/null
+++ b/docs_src/extra_data_types/tutorial001_an_py39.py
@@ -0,0 +1,28 @@
+from datetime import datetime, time, timedelta
+from typing import Annotated, Union
+from uuid import UUID
+
+from fastapi import Body, FastAPI
+
+app = FastAPI()
+
+
+@app.put("/items/{item_id}")
+async def read_items(
+ item_id: UUID,
+ start_datetime: Annotated[Union[datetime, None], Body()] = None,
+ end_datetime: Annotated[Union[datetime, None], Body()] = None,
+ repeat_at: Annotated[Union[time, None], Body()] = None,
+ process_after: Annotated[Union[timedelta, None], Body()] = None,
+):
+ start_process = start_datetime + process_after
+ duration = end_datetime - start_process
+ return {
+ "item_id": item_id,
+ "start_datetime": start_datetime,
+ "end_datetime": end_datetime,
+ "repeat_at": repeat_at,
+ "process_after": process_after,
+ "start_process": start_process,
+ "duration": duration,
+ }
diff --git a/docs_src/header_params/tutorial001_an.py b/docs_src/header_params/tutorial001_an.py
new file mode 100644
index 000000000..816c00086
--- /dev/null
+++ b/docs_src/header_params/tutorial001_an.py
@@ -0,0 +1,11 @@
+from typing import Union
+
+from fastapi import FastAPI, Header
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(user_agent: Annotated[Union[str, None], Header()] = None):
+ return {"User-Agent": user_agent}
diff --git a/docs_src/header_params/tutorial001_an_py310.py b/docs_src/header_params/tutorial001_an_py310.py
new file mode 100644
index 000000000..4ba5e1bfb
--- /dev/null
+++ b/docs_src/header_params/tutorial001_an_py310.py
@@ -0,0 +1,10 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Header
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(user_agent: Annotated[str | None, Header()] = None):
+ return {"User-Agent": user_agent}
diff --git a/docs_src/header_params/tutorial001_an_py39.py b/docs_src/header_params/tutorial001_an_py39.py
new file mode 100644
index 000000000..1fbe3bb99
--- /dev/null
+++ b/docs_src/header_params/tutorial001_an_py39.py
@@ -0,0 +1,10 @@
+from typing import Annotated, Union
+
+from fastapi import FastAPI, Header
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(user_agent: Annotated[Union[str, None], Header()] = None):
+ return {"User-Agent": user_agent}
diff --git a/docs_src/header_params/tutorial002_an.py b/docs_src/header_params/tutorial002_an.py
new file mode 100644
index 000000000..65d972d46
--- /dev/null
+++ b/docs_src/header_params/tutorial002_an.py
@@ -0,0 +1,15 @@
+from typing import Union
+
+from fastapi import FastAPI, Header
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ strange_header: Annotated[
+ Union[str, None], Header(convert_underscores=False)
+ ] = None
+):
+ return {"strange_header": strange_header}
diff --git a/docs_src/header_params/tutorial002_an_py310.py b/docs_src/header_params/tutorial002_an_py310.py
new file mode 100644
index 000000000..b340647b6
--- /dev/null
+++ b/docs_src/header_params/tutorial002_an_py310.py
@@ -0,0 +1,12 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Header
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ strange_header: Annotated[str | None, Header(convert_underscores=False)] = None
+):
+ return {"strange_header": strange_header}
diff --git a/docs_src/header_params/tutorial002_an_py39.py b/docs_src/header_params/tutorial002_an_py39.py
new file mode 100644
index 000000000..7f6a99f9c
--- /dev/null
+++ b/docs_src/header_params/tutorial002_an_py39.py
@@ -0,0 +1,14 @@
+from typing import Annotated, Union
+
+from fastapi import FastAPI, Header
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ strange_header: Annotated[
+ Union[str, None], Header(convert_underscores=False)
+ ] = None
+):
+ return {"strange_header": strange_header}
diff --git a/docs_src/header_params/tutorial003_an.py b/docs_src/header_params/tutorial003_an.py
new file mode 100644
index 000000000..5406fd1f8
--- /dev/null
+++ b/docs_src/header_params/tutorial003_an.py
@@ -0,0 +1,11 @@
+from typing import List, Union
+
+from fastapi import FastAPI, Header
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(x_token: Annotated[Union[List[str], None], Header()] = None):
+ return {"X-Token values": x_token}
diff --git a/docs_src/header_params/tutorial003_an_py310.py b/docs_src/header_params/tutorial003_an_py310.py
new file mode 100644
index 000000000..0e78cf029
--- /dev/null
+++ b/docs_src/header_params/tutorial003_an_py310.py
@@ -0,0 +1,10 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Header
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(x_token: Annotated[list[str] | None, Header()] = None):
+ return {"X-Token values": x_token}
diff --git a/docs_src/header_params/tutorial003_an_py39.py b/docs_src/header_params/tutorial003_an_py39.py
new file mode 100644
index 000000000..c1dd49961
--- /dev/null
+++ b/docs_src/header_params/tutorial003_an_py39.py
@@ -0,0 +1,10 @@
+from typing import Annotated, List, Union
+
+from fastapi import FastAPI, Header
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(x_token: Annotated[Union[List[str], None], Header()] = None):
+ return {"X-Token values": x_token}
diff --git a/docs_src/path_params_numeric_validations/tutorial001_an.py b/docs_src/path_params_numeric_validations/tutorial001_an.py
new file mode 100644
index 000000000..621be7b04
--- /dev/null
+++ b/docs_src/path_params_numeric_validations/tutorial001_an.py
@@ -0,0 +1,17 @@
+from typing import Union
+
+from fastapi import FastAPI, Path, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ item_id: Annotated[int, Path(title="The ID of the item to get")],
+ q: Annotated[Union[str, None], Query(alias="item-query")] = None,
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/path_params_numeric_validations/tutorial001_an_py310.py b/docs_src/path_params_numeric_validations/tutorial001_an_py310.py
new file mode 100644
index 000000000..c4db263f0
--- /dev/null
+++ b/docs_src/path_params_numeric_validations/tutorial001_an_py310.py
@@ -0,0 +1,16 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Path, Query
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ item_id: Annotated[int, Path(title="The ID of the item to get")],
+ q: Annotated[str | None, Query(alias="item-query")] = None,
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/path_params_numeric_validations/tutorial001_an_py39.py b/docs_src/path_params_numeric_validations/tutorial001_an_py39.py
new file mode 100644
index 000000000..b36315a46
--- /dev/null
+++ b/docs_src/path_params_numeric_validations/tutorial001_an_py39.py
@@ -0,0 +1,16 @@
+from typing import Annotated, Union
+
+from fastapi import FastAPI, Path, Query
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ item_id: Annotated[int, Path(title="The ID of the item to get")],
+ q: Annotated[Union[str, None], Query(alias="item-query")] = None,
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/path_params_numeric_validations/tutorial002_an.py b/docs_src/path_params_numeric_validations/tutorial002_an.py
new file mode 100644
index 000000000..322f8cf0b
--- /dev/null
+++ b/docs_src/path_params_numeric_validations/tutorial002_an.py
@@ -0,0 +1,14 @@
+from fastapi import FastAPI, Path
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ q: str, item_id: Annotated[int, Path(title="The ID of the item to get")]
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/path_params_numeric_validations/tutorial002_an_py39.py b/docs_src/path_params_numeric_validations/tutorial002_an_py39.py
new file mode 100644
index 000000000..cd882abb2
--- /dev/null
+++ b/docs_src/path_params_numeric_validations/tutorial002_an_py39.py
@@ -0,0 +1,15 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Path
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ q: str, item_id: Annotated[int, Path(title="The ID of the item to get")]
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/path_params_numeric_validations/tutorial003_an.py b/docs_src/path_params_numeric_validations/tutorial003_an.py
new file mode 100644
index 000000000..d0fa8b3db
--- /dev/null
+++ b/docs_src/path_params_numeric_validations/tutorial003_an.py
@@ -0,0 +1,14 @@
+from fastapi import FastAPI, Path
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ item_id: Annotated[int, Path(title="The ID of the item to get")], q: str
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/path_params_numeric_validations/tutorial003_an_py39.py b/docs_src/path_params_numeric_validations/tutorial003_an_py39.py
new file mode 100644
index 000000000..1588556e7
--- /dev/null
+++ b/docs_src/path_params_numeric_validations/tutorial003_an_py39.py
@@ -0,0 +1,15 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Path
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ item_id: Annotated[int, Path(title="The ID of the item to get")], q: str
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/path_params_numeric_validations/tutorial004_an.py b/docs_src/path_params_numeric_validations/tutorial004_an.py
new file mode 100644
index 000000000..ffc50f6c5
--- /dev/null
+++ b/docs_src/path_params_numeric_validations/tutorial004_an.py
@@ -0,0 +1,14 @@
+from fastapi import FastAPI, Path
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)], q: str
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/path_params_numeric_validations/tutorial004_an_py39.py b/docs_src/path_params_numeric_validations/tutorial004_an_py39.py
new file mode 100644
index 000000000..f67f6450e
--- /dev/null
+++ b/docs_src/path_params_numeric_validations/tutorial004_an_py39.py
@@ -0,0 +1,15 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Path
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)], q: str
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/path_params_numeric_validations/tutorial005_an.py b/docs_src/path_params_numeric_validations/tutorial005_an.py
new file mode 100644
index 000000000..433c69129
--- /dev/null
+++ b/docs_src/path_params_numeric_validations/tutorial005_an.py
@@ -0,0 +1,15 @@
+from fastapi import FastAPI, Path
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ item_id: Annotated[int, Path(title="The ID of the item to get", gt=0, le=1000)],
+ q: str,
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/path_params_numeric_validations/tutorial005_an_py39.py b/docs_src/path_params_numeric_validations/tutorial005_an_py39.py
new file mode 100644
index 000000000..571dd583c
--- /dev/null
+++ b/docs_src/path_params_numeric_validations/tutorial005_an_py39.py
@@ -0,0 +1,16 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Path
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ item_id: Annotated[int, Path(title="The ID of the item to get", gt=0, le=1000)],
+ q: str,
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/path_params_numeric_validations/tutorial006_an.py b/docs_src/path_params_numeric_validations/tutorial006_an.py
new file mode 100644
index 000000000..22a143623
--- /dev/null
+++ b/docs_src/path_params_numeric_validations/tutorial006_an.py
@@ -0,0 +1,17 @@
+from fastapi import FastAPI, Path, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ *,
+ item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],
+ q: str,
+ size: Annotated[float, Query(gt=0, lt=10.5)],
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/path_params_numeric_validations/tutorial006_an_py39.py b/docs_src/path_params_numeric_validations/tutorial006_an_py39.py
new file mode 100644
index 000000000..804751893
--- /dev/null
+++ b/docs_src/path_params_numeric_validations/tutorial006_an_py39.py
@@ -0,0 +1,18 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Path, Query
+
+app = FastAPI()
+
+
+@app.get("/items/{item_id}")
+async def read_items(
+ *,
+ item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],
+ q: str,
+ size: Annotated[float, Query(gt=0, lt=10.5)],
+):
+ results = {"item_id": item_id}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/python_types/tutorial013.py b/docs_src/python_types/tutorial013.py
new file mode 100644
index 000000000..0ec773519
--- /dev/null
+++ b/docs_src/python_types/tutorial013.py
@@ -0,0 +1,5 @@
+from typing_extensions import Annotated
+
+
+def say_hello(name: Annotated[str, "this is just metadata"]) -> str:
+ return f"Hello {name}"
diff --git a/docs_src/python_types/tutorial013_py39.py b/docs_src/python_types/tutorial013_py39.py
new file mode 100644
index 000000000..65a0eaa93
--- /dev/null
+++ b/docs_src/python_types/tutorial013_py39.py
@@ -0,0 +1,5 @@
+from typing import Annotated
+
+
+def say_hello(name: Annotated[str, "this is just metadata"]) -> str:
+ return f"Hello {name}"
diff --git a/docs_src/query_params_str_validations/tutorial002_an.py b/docs_src/query_params_str_validations/tutorial002_an.py
new file mode 100644
index 000000000..cb1b38940
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial002_an.py
@@ -0,0 +1,14 @@
+from typing import Union
+
+from fastapi import FastAPI, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[Union[str, None], Query(max_length=50)] = None):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial002_an_py310.py b/docs_src/query_params_str_validations/tutorial002_an_py310.py
new file mode 100644
index 000000000..66ee7451b
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial002_an_py310.py
@@ -0,0 +1,13 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[str | None, Query(max_length=50)] = None):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial003_an.py b/docs_src/query_params_str_validations/tutorial003_an.py
new file mode 100644
index 000000000..a3665f6a8
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial003_an.py
@@ -0,0 +1,16 @@
+from typing import Union
+
+from fastapi import FastAPI, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ q: Annotated[Union[str, None], Query(min_length=3, max_length=50)] = None
+):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial003_an_py310.py b/docs_src/query_params_str_validations/tutorial003_an_py310.py
new file mode 100644
index 000000000..836af04de
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial003_an_py310.py
@@ -0,0 +1,15 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ q: Annotated[str | None, Query(min_length=3, max_length=50)] = None
+):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial003_an_py39.py b/docs_src/query_params_str_validations/tutorial003_an_py39.py
new file mode 100644
index 000000000..87a426839
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial003_an_py39.py
@@ -0,0 +1,15 @@
+from typing import Annotated, Union
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ q: Annotated[Union[str, None], Query(min_length=3, max_length=50)] = None
+):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial004_an.py b/docs_src/query_params_str_validations/tutorial004_an.py
new file mode 100644
index 000000000..5346b997b
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial004_an.py
@@ -0,0 +1,18 @@
+from typing import Union
+
+from fastapi import FastAPI, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ q: Annotated[
+ Union[str, None], Query(min_length=3, max_length=50, regex="^fixedquery$")
+ ] = None
+):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial004_an_py310.py b/docs_src/query_params_str_validations/tutorial004_an_py310.py
new file mode 100644
index 000000000..8fd375b3d
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial004_an_py310.py
@@ -0,0 +1,17 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ q: Annotated[
+ str | None, Query(min_length=3, max_length=50, regex="^fixedquery$")
+ ] = None
+):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial004_an_py39.py b/docs_src/query_params_str_validations/tutorial004_an_py39.py
new file mode 100644
index 000000000..2fd82db75
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial004_an_py39.py
@@ -0,0 +1,17 @@
+from typing import Annotated, Union
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ q: Annotated[
+ Union[str, None], Query(min_length=3, max_length=50, regex="^fixedquery$")
+ ] = None
+):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial005_an.py b/docs_src/query_params_str_validations/tutorial005_an.py
new file mode 100644
index 000000000..452d4d38d
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial005_an.py
@@ -0,0 +1,12 @@
+from fastapi import FastAPI, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[str, Query(min_length=3)] = "fixedquery"):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial005_an_py39.py b/docs_src/query_params_str_validations/tutorial005_an_py39.py
new file mode 100644
index 000000000..b1f6046b5
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial005_an_py39.py
@@ -0,0 +1,13 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[str, Query(min_length=3)] = "fixedquery"):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial006_an.py b/docs_src/query_params_str_validations/tutorial006_an.py
new file mode 100644
index 000000000..559480d2b
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial006_an.py
@@ -0,0 +1,12 @@
+from fastapi import FastAPI, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[str, Query(min_length=3)]):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial006_an_py39.py b/docs_src/query_params_str_validations/tutorial006_an_py39.py
new file mode 100644
index 000000000..3b4a676d2
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial006_an_py39.py
@@ -0,0 +1,13 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[str, Query(min_length=3)]):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial006b_an.py b/docs_src/query_params_str_validations/tutorial006b_an.py
new file mode 100644
index 000000000..ea3b02583
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial006b_an.py
@@ -0,0 +1,12 @@
+from fastapi import FastAPI, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[str, Query(min_length=3)] = ...):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial006b_an_py39.py b/docs_src/query_params_str_validations/tutorial006b_an_py39.py
new file mode 100644
index 000000000..687a9f544
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial006b_an_py39.py
@@ -0,0 +1,13 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[str, Query(min_length=3)] = ...):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial006c_an.py b/docs_src/query_params_str_validations/tutorial006c_an.py
new file mode 100644
index 000000000..10bf26a57
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial006c_an.py
@@ -0,0 +1,14 @@
+from typing import Union
+
+from fastapi import FastAPI, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[Union[str, None], Query(min_length=3)] = ...):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial006c_an_py310.py b/docs_src/query_params_str_validations/tutorial006c_an_py310.py
new file mode 100644
index 000000000..1ab0a7d53
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial006c_an_py310.py
@@ -0,0 +1,13 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[str | None, Query(min_length=3)] = ...):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial006c_an_py39.py b/docs_src/query_params_str_validations/tutorial006c_an_py39.py
new file mode 100644
index 000000000..ac1273331
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial006c_an_py39.py
@@ -0,0 +1,13 @@
+from typing import Annotated, Union
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[Union[str, None], Query(min_length=3)] = ...):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial006d_an.py b/docs_src/query_params_str_validations/tutorial006d_an.py
new file mode 100644
index 000000000..bc8283e15
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial006d_an.py
@@ -0,0 +1,13 @@
+from fastapi import FastAPI, Query
+from pydantic import Required
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[str, Query(min_length=3)] = Required):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial006d_an_py39.py b/docs_src/query_params_str_validations/tutorial006d_an_py39.py
new file mode 100644
index 000000000..035d9e3bd
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial006d_an_py39.py
@@ -0,0 +1,14 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Query
+from pydantic import Required
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[str, Query(min_length=3)] = Required):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial007_an.py b/docs_src/query_params_str_validations/tutorial007_an.py
new file mode 100644
index 000000000..3bc85cc0c
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial007_an.py
@@ -0,0 +1,16 @@
+from typing import Union
+
+from fastapi import FastAPI, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ q: Annotated[Union[str, None], Query(title="Query string", min_length=3)] = None
+):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial007_an_py310.py b/docs_src/query_params_str_validations/tutorial007_an_py310.py
new file mode 100644
index 000000000..5933911fd
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial007_an_py310.py
@@ -0,0 +1,15 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ q: Annotated[str | None, Query(title="Query string", min_length=3)] = None
+):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial007_an_py39.py b/docs_src/query_params_str_validations/tutorial007_an_py39.py
new file mode 100644
index 000000000..dafa1c5c9
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial007_an_py39.py
@@ -0,0 +1,15 @@
+from typing import Annotated, Union
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ q: Annotated[Union[str, None], Query(title="Query string", min_length=3)] = None
+):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial008_an.py b/docs_src/query_params_str_validations/tutorial008_an.py
new file mode 100644
index 000000000..5699f1e88
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial008_an.py
@@ -0,0 +1,23 @@
+from typing import Union
+
+from fastapi import FastAPI, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ q: Annotated[
+ Union[str, None],
+ Query(
+ title="Query string",
+ description="Query string for the items to search in the database that have a good match",
+ min_length=3,
+ ),
+ ] = None
+):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial008_an_py310.py b/docs_src/query_params_str_validations/tutorial008_an_py310.py
new file mode 100644
index 000000000..4aaadf8b4
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial008_an_py310.py
@@ -0,0 +1,22 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ q: Annotated[
+ str | None,
+ Query(
+ title="Query string",
+ description="Query string for the items to search in the database that have a good match",
+ min_length=3,
+ ),
+ ] = None
+):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial008_an_py39.py b/docs_src/query_params_str_validations/tutorial008_an_py39.py
new file mode 100644
index 000000000..1c3b36176
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial008_an_py39.py
@@ -0,0 +1,22 @@
+from typing import Annotated, Union
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ q: Annotated[
+ Union[str, None],
+ Query(
+ title="Query string",
+ description="Query string for the items to search in the database that have a good match",
+ min_length=3,
+ ),
+ ] = None
+):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial009_an.py b/docs_src/query_params_str_validations/tutorial009_an.py
new file mode 100644
index 000000000..2894e2d51
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial009_an.py
@@ -0,0 +1,14 @@
+from typing import Union
+
+from fastapi import FastAPI, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[Union[str, None], Query(alias="item-query")] = None):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial009_an_py310.py b/docs_src/query_params_str_validations/tutorial009_an_py310.py
new file mode 100644
index 000000000..d11753362
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial009_an_py310.py
@@ -0,0 +1,13 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[str | None, Query(alias="item-query")] = None):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial009_an_py39.py b/docs_src/query_params_str_validations/tutorial009_an_py39.py
new file mode 100644
index 000000000..70a89e613
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial009_an_py39.py
@@ -0,0 +1,13 @@
+from typing import Annotated, Union
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[Union[str, None], Query(alias="item-query")] = None):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial010_an.py b/docs_src/query_params_str_validations/tutorial010_an.py
new file mode 100644
index 000000000..8995f3f57
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial010_an.py
@@ -0,0 +1,27 @@
+from typing import Union
+
+from fastapi import FastAPI, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ q: Annotated[
+ Union[str, None],
+ Query(
+ alias="item-query",
+ title="Query string",
+ description="Query string for the items to search in the database that have a good match",
+ min_length=3,
+ max_length=50,
+ regex="^fixedquery$",
+ deprecated=True,
+ ),
+ ] = None
+):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial010_an_py310.py b/docs_src/query_params_str_validations/tutorial010_an_py310.py
new file mode 100644
index 000000000..cfa81926c
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial010_an_py310.py
@@ -0,0 +1,26 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ q: Annotated[
+ str | None,
+ Query(
+ alias="item-query",
+ title="Query string",
+ description="Query string for the items to search in the database that have a good match",
+ min_length=3,
+ max_length=50,
+ regex="^fixedquery$",
+ deprecated=True,
+ ),
+ ] = None
+):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial010_an_py39.py b/docs_src/query_params_str_validations/tutorial010_an_py39.py
new file mode 100644
index 000000000..220eaabf4
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial010_an_py39.py
@@ -0,0 +1,26 @@
+from typing import Annotated, Union
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ q: Annotated[
+ Union[str, None],
+ Query(
+ alias="item-query",
+ title="Query string",
+ description="Query string for the items to search in the database that have a good match",
+ min_length=3,
+ max_length=50,
+ regex="^fixedquery$",
+ deprecated=True,
+ ),
+ ] = None
+):
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
+ if q:
+ results.update({"q": q})
+ return results
diff --git a/docs_src/query_params_str_validations/tutorial011_an.py b/docs_src/query_params_str_validations/tutorial011_an.py
new file mode 100644
index 000000000..8ed699337
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial011_an.py
@@ -0,0 +1,12 @@
+from typing import List, Union
+
+from fastapi import FastAPI, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[Union[List[str], None], Query()] = None):
+ query_items = {"q": q}
+ return query_items
diff --git a/docs_src/query_params_str_validations/tutorial011_an_py310.py b/docs_src/query_params_str_validations/tutorial011_an_py310.py
new file mode 100644
index 000000000..5dad4bfde
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial011_an_py310.py
@@ -0,0 +1,11 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[list[str] | None, Query()] = None):
+ query_items = {"q": q}
+ return query_items
diff --git a/docs_src/query_params_str_validations/tutorial011_an_py39.py b/docs_src/query_params_str_validations/tutorial011_an_py39.py
new file mode 100644
index 000000000..416e3990d
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial011_an_py39.py
@@ -0,0 +1,11 @@
+from typing import Annotated, Union
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[Union[list[str], None], Query()] = None):
+ query_items = {"q": q}
+ return query_items
diff --git a/docs_src/query_params_str_validations/tutorial012_an.py b/docs_src/query_params_str_validations/tutorial012_an.py
new file mode 100644
index 000000000..261af250a
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial012_an.py
@@ -0,0 +1,12 @@
+from typing import List
+
+from fastapi import FastAPI, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[List[str], Query()] = ["foo", "bar"]):
+ query_items = {"q": q}
+ return query_items
diff --git a/docs_src/query_params_str_validations/tutorial012_an_py39.py b/docs_src/query_params_str_validations/tutorial012_an_py39.py
new file mode 100644
index 000000000..9b5a9c2fb
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial012_an_py39.py
@@ -0,0 +1,11 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[list[str], Query()] = ["foo", "bar"]):
+ query_items = {"q": q}
+ return query_items
diff --git a/docs_src/query_params_str_validations/tutorial013_an.py b/docs_src/query_params_str_validations/tutorial013_an.py
new file mode 100644
index 000000000..f12a25055
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial013_an.py
@@ -0,0 +1,10 @@
+from fastapi import FastAPI, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[list, Query()] = []):
+ query_items = {"q": q}
+ return query_items
diff --git a/docs_src/query_params_str_validations/tutorial013_an_py39.py b/docs_src/query_params_str_validations/tutorial013_an_py39.py
new file mode 100644
index 000000000..602734145
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial013_an_py39.py
@@ -0,0 +1,11 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(q: Annotated[list, Query()] = []):
+ query_items = {"q": q}
+ return query_items
diff --git a/docs_src/query_params_str_validations/tutorial014_an.py b/docs_src/query_params_str_validations/tutorial014_an.py
new file mode 100644
index 000000000..a9a9c4427
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial014_an.py
@@ -0,0 +1,16 @@
+from typing import Union
+
+from fastapi import FastAPI, Query
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ hidden_query: Annotated[Union[str, None], Query(include_in_schema=False)] = None
+):
+ if hidden_query:
+ return {"hidden_query": hidden_query}
+ else:
+ return {"hidden_query": "Not found"}
diff --git a/docs_src/query_params_str_validations/tutorial014_an_py310.py b/docs_src/query_params_str_validations/tutorial014_an_py310.py
new file mode 100644
index 000000000..5fba54150
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial014_an_py310.py
@@ -0,0 +1,15 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ hidden_query: Annotated[str | None, Query(include_in_schema=False)] = None
+):
+ if hidden_query:
+ return {"hidden_query": hidden_query}
+ else:
+ return {"hidden_query": "Not found"}
diff --git a/docs_src/query_params_str_validations/tutorial014_an_py39.py b/docs_src/query_params_str_validations/tutorial014_an_py39.py
new file mode 100644
index 000000000..b07985210
--- /dev/null
+++ b/docs_src/query_params_str_validations/tutorial014_an_py39.py
@@ -0,0 +1,15 @@
+from typing import Annotated, Union
+
+from fastapi import FastAPI, Query
+
+app = FastAPI()
+
+
+@app.get("/items/")
+async def read_items(
+ hidden_query: Annotated[Union[str, None], Query(include_in_schema=False)] = None
+):
+ if hidden_query:
+ return {"hidden_query": hidden_query}
+ else:
+ return {"hidden_query": "Not found"}
diff --git a/docs_src/request_files/tutorial001_02_an.py b/docs_src/request_files/tutorial001_02_an.py
new file mode 100644
index 000000000..5007fef15
--- /dev/null
+++ b/docs_src/request_files/tutorial001_02_an.py
@@ -0,0 +1,22 @@
+from typing import Union
+
+from fastapi import FastAPI, File, UploadFile
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_file(file: Annotated[Union[bytes, None], File()] = None):
+ if not file:
+ return {"message": "No file sent"}
+ else:
+ return {"file_size": len(file)}
+
+
+@app.post("/uploadfile/")
+async def create_upload_file(file: Union[UploadFile, None] = None):
+ if not file:
+ return {"message": "No upload file sent"}
+ else:
+ return {"filename": file.filename}
diff --git a/docs_src/request_files/tutorial001_02_an_py310.py b/docs_src/request_files/tutorial001_02_an_py310.py
new file mode 100644
index 000000000..9b80321b4
--- /dev/null
+++ b/docs_src/request_files/tutorial001_02_an_py310.py
@@ -0,0 +1,21 @@
+from typing import Annotated
+
+from fastapi import FastAPI, File, UploadFile
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_file(file: Annotated[bytes | None, File()] = None):
+ if not file:
+ return {"message": "No file sent"}
+ else:
+ return {"file_size": len(file)}
+
+
+@app.post("/uploadfile/")
+async def create_upload_file(file: UploadFile | None = None):
+ if not file:
+ return {"message": "No upload file sent"}
+ else:
+ return {"filename": file.filename}
diff --git a/docs_src/request_files/tutorial001_02_an_py39.py b/docs_src/request_files/tutorial001_02_an_py39.py
new file mode 100644
index 000000000..bb090ff6c
--- /dev/null
+++ b/docs_src/request_files/tutorial001_02_an_py39.py
@@ -0,0 +1,21 @@
+from typing import Annotated, Union
+
+from fastapi import FastAPI, File, UploadFile
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_file(file: Annotated[Union[bytes, None], File()] = None):
+ if not file:
+ return {"message": "No file sent"}
+ else:
+ return {"file_size": len(file)}
+
+
+@app.post("/uploadfile/")
+async def create_upload_file(file: Union[UploadFile, None] = None):
+ if not file:
+ return {"message": "No upload file sent"}
+ else:
+ return {"filename": file.filename}
diff --git a/docs_src/request_files/tutorial001_03_an.py b/docs_src/request_files/tutorial001_03_an.py
new file mode 100644
index 000000000..8a6b0a245
--- /dev/null
+++ b/docs_src/request_files/tutorial001_03_an.py
@@ -0,0 +1,16 @@
+from fastapi import FastAPI, File, UploadFile
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_file(file: Annotated[bytes, File(description="A file read as bytes")]):
+ return {"file_size": len(file)}
+
+
+@app.post("/uploadfile/")
+async def create_upload_file(
+ file: Annotated[UploadFile, File(description="A file read as UploadFile")],
+):
+ return {"filename": file.filename}
diff --git a/docs_src/request_files/tutorial001_03_an_py39.py b/docs_src/request_files/tutorial001_03_an_py39.py
new file mode 100644
index 000000000..93098a677
--- /dev/null
+++ b/docs_src/request_files/tutorial001_03_an_py39.py
@@ -0,0 +1,17 @@
+from typing import Annotated
+
+from fastapi import FastAPI, File, UploadFile
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_file(file: Annotated[bytes, File(description="A file read as bytes")]):
+ return {"file_size": len(file)}
+
+
+@app.post("/uploadfile/")
+async def create_upload_file(
+ file: Annotated[UploadFile, File(description="A file read as UploadFile")],
+):
+ return {"filename": file.filename}
diff --git a/docs_src/request_files/tutorial001_an.py b/docs_src/request_files/tutorial001_an.py
new file mode 100644
index 000000000..ca2f76d5c
--- /dev/null
+++ b/docs_src/request_files/tutorial001_an.py
@@ -0,0 +1,14 @@
+from fastapi import FastAPI, File, UploadFile
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_file(file: Annotated[bytes, File()]):
+ return {"file_size": len(file)}
+
+
+@app.post("/uploadfile/")
+async def create_upload_file(file: UploadFile):
+ return {"filename": file.filename}
diff --git a/docs_src/request_files/tutorial001_an_py39.py b/docs_src/request_files/tutorial001_an_py39.py
new file mode 100644
index 000000000..26a767221
--- /dev/null
+++ b/docs_src/request_files/tutorial001_an_py39.py
@@ -0,0 +1,15 @@
+from typing import Annotated
+
+from fastapi import FastAPI, File, UploadFile
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_file(file: Annotated[bytes, File()]):
+ return {"file_size": len(file)}
+
+
+@app.post("/uploadfile/")
+async def create_upload_file(file: UploadFile):
+ return {"filename": file.filename}
diff --git a/docs_src/request_files/tutorial002_an.py b/docs_src/request_files/tutorial002_an.py
new file mode 100644
index 000000000..eaa90da2b
--- /dev/null
+++ b/docs_src/request_files/tutorial002_an.py
@@ -0,0 +1,34 @@
+from typing import List
+
+from fastapi import FastAPI, File, UploadFile
+from fastapi.responses import HTMLResponse
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_files(files: Annotated[List[bytes], File()]):
+ return {"file_sizes": [len(file) for file in files]}
+
+
+@app.post("/uploadfiles/")
+async def create_upload_files(files: List[UploadFile]):
+ return {"filenames": [file.filename for file in files]}
+
+
+@app.get("/")
+async def main():
+ content = """
+
+
+
+
+ """
+ return HTMLResponse(content=content)
diff --git a/docs_src/request_files/tutorial002_an_py39.py b/docs_src/request_files/tutorial002_an_py39.py
new file mode 100644
index 000000000..db524ceab
--- /dev/null
+++ b/docs_src/request_files/tutorial002_an_py39.py
@@ -0,0 +1,33 @@
+from typing import Annotated
+
+from fastapi import FastAPI, File, UploadFile
+from fastapi.responses import HTMLResponse
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_files(files: Annotated[list[bytes], File()]):
+ return {"file_sizes": [len(file) for file in files]}
+
+
+@app.post("/uploadfiles/")
+async def create_upload_files(files: list[UploadFile]):
+ return {"filenames": [file.filename for file in files]}
+
+
+@app.get("/")
+async def main():
+ content = """
+
+
+
+
+ """
+ return HTMLResponse(content=content)
diff --git a/docs_src/request_files/tutorial003_an.py b/docs_src/request_files/tutorial003_an.py
new file mode 100644
index 000000000..2238e3c94
--- /dev/null
+++ b/docs_src/request_files/tutorial003_an.py
@@ -0,0 +1,40 @@
+from typing import List
+
+from fastapi import FastAPI, File, UploadFile
+from fastapi.responses import HTMLResponse
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_files(
+ files: Annotated[List[bytes], File(description="Multiple files as bytes")],
+):
+ return {"file_sizes": [len(file) for file in files]}
+
+
+@app.post("/uploadfiles/")
+async def create_upload_files(
+ files: Annotated[
+ List[UploadFile], File(description="Multiple files as UploadFile")
+ ],
+):
+ return {"filenames": [file.filename for file in files]}
+
+
+@app.get("/")
+async def main():
+ content = """
+
+
+
+
+ """
+ return HTMLResponse(content=content)
diff --git a/docs_src/request_files/tutorial003_an_py39.py b/docs_src/request_files/tutorial003_an_py39.py
new file mode 100644
index 000000000..5a8c5dab5
--- /dev/null
+++ b/docs_src/request_files/tutorial003_an_py39.py
@@ -0,0 +1,39 @@
+from typing import Annotated
+
+from fastapi import FastAPI, File, UploadFile
+from fastapi.responses import HTMLResponse
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_files(
+ files: Annotated[list[bytes], File(description="Multiple files as bytes")],
+):
+ return {"file_sizes": [len(file) for file in files]}
+
+
+@app.post("/uploadfiles/")
+async def create_upload_files(
+ files: Annotated[
+ list[UploadFile], File(description="Multiple files as UploadFile")
+ ],
+):
+ return {"filenames": [file.filename for file in files]}
+
+
+@app.get("/")
+async def main():
+ content = """
+
+
+
+
+ """
+ return HTMLResponse(content=content)
diff --git a/docs_src/request_forms/tutorial001_an.py b/docs_src/request_forms/tutorial001_an.py
new file mode 100644
index 000000000..677fbf2db
--- /dev/null
+++ b/docs_src/request_forms/tutorial001_an.py
@@ -0,0 +1,9 @@
+from fastapi import FastAPI, Form
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.post("/login/")
+async def login(username: Annotated[str, Form()], password: Annotated[str, Form()]):
+ return {"username": username}
diff --git a/docs_src/request_forms/tutorial001_an_py39.py b/docs_src/request_forms/tutorial001_an_py39.py
new file mode 100644
index 000000000..8e9d2ea53
--- /dev/null
+++ b/docs_src/request_forms/tutorial001_an_py39.py
@@ -0,0 +1,10 @@
+from typing import Annotated
+
+from fastapi import FastAPI, Form
+
+app = FastAPI()
+
+
+@app.post("/login/")
+async def login(username: Annotated[str, Form()], password: Annotated[str, Form()]):
+ return {"username": username}
diff --git a/docs_src/request_forms_and_files/tutorial001_an.py b/docs_src/request_forms_and_files/tutorial001_an.py
new file mode 100644
index 000000000..0ea285ac8
--- /dev/null
+++ b/docs_src/request_forms_and_files/tutorial001_an.py
@@ -0,0 +1,17 @@
+from fastapi import FastAPI, File, Form, UploadFile
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_file(
+ file: Annotated[bytes, File()],
+ fileb: Annotated[UploadFile, File()],
+ token: Annotated[str, Form()],
+):
+ return {
+ "file_size": len(file),
+ "token": token,
+ "fileb_content_type": fileb.content_type,
+ }
diff --git a/docs_src/request_forms_and_files/tutorial001_an_py39.py b/docs_src/request_forms_and_files/tutorial001_an_py39.py
new file mode 100644
index 000000000..12cc43e50
--- /dev/null
+++ b/docs_src/request_forms_and_files/tutorial001_an_py39.py
@@ -0,0 +1,18 @@
+from typing import Annotated
+
+from fastapi import FastAPI, File, Form, UploadFile
+
+app = FastAPI()
+
+
+@app.post("/files/")
+async def create_file(
+ file: Annotated[bytes, File()],
+ fileb: Annotated[UploadFile, File()],
+ token: Annotated[str, Form()],
+):
+ return {
+ "file_size": len(file),
+ "token": token,
+ "fileb_content_type": fileb.content_type,
+ }
diff --git a/docs_src/schema_extra_example/tutorial003_an.py b/docs_src/schema_extra_example/tutorial003_an.py
new file mode 100644
index 000000000..1dec555a9
--- /dev/null
+++ b/docs_src/schema_extra_example/tutorial003_an.py
@@ -0,0 +1,33 @@
+from typing import Union
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: Union[str, None] = None
+ price: float
+ tax: Union[float, None] = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(
+ item_id: int,
+ item: Annotated[
+ Item,
+ Body(
+ example={
+ "name": "Foo",
+ "description": "A very nice Item",
+ "price": 35.4,
+ "tax": 3.2,
+ },
+ ),
+ ],
+):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs_src/schema_extra_example/tutorial003_an_py310.py b/docs_src/schema_extra_example/tutorial003_an_py310.py
new file mode 100644
index 000000000..9edaddfb8
--- /dev/null
+++ b/docs_src/schema_extra_example/tutorial003_an_py310.py
@@ -0,0 +1,32 @@
+from typing import Annotated
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: str | None = None
+ price: float
+ tax: float | None = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(
+ item_id: int,
+ item: Annotated[
+ Item,
+ Body(
+ example={
+ "name": "Foo",
+ "description": "A very nice Item",
+ "price": 35.4,
+ "tax": 3.2,
+ },
+ ),
+ ],
+):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs_src/schema_extra_example/tutorial003_an_py39.py b/docs_src/schema_extra_example/tutorial003_an_py39.py
new file mode 100644
index 000000000..fe08847d9
--- /dev/null
+++ b/docs_src/schema_extra_example/tutorial003_an_py39.py
@@ -0,0 +1,32 @@
+from typing import Annotated, Union
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: Union[str, None] = None
+ price: float
+ tax: Union[float, None] = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(
+ item_id: int,
+ item: Annotated[
+ Item,
+ Body(
+ example={
+ "name": "Foo",
+ "description": "A very nice Item",
+ "price": 35.4,
+ "tax": 3.2,
+ },
+ ),
+ ],
+):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs_src/schema_extra_example/tutorial004_an.py b/docs_src/schema_extra_example/tutorial004_an.py
new file mode 100644
index 000000000..82c9a92ac
--- /dev/null
+++ b/docs_src/schema_extra_example/tutorial004_an.py
@@ -0,0 +1,55 @@
+from typing import Union
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: Union[str, None] = None
+ price: float
+ tax: Union[float, None] = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(
+ *,
+ item_id: int,
+ item: Annotated[
+ Item,
+ Body(
+ examples={
+ "normal": {
+ "summary": "A normal example",
+ "description": "A **normal** item works correctly.",
+ "value": {
+ "name": "Foo",
+ "description": "A very nice Item",
+ "price": 35.4,
+ "tax": 3.2,
+ },
+ },
+ "converted": {
+ "summary": "An example with converted data",
+ "description": "FastAPI can convert price `strings` to actual `numbers` automatically",
+ "value": {
+ "name": "Bar",
+ "price": "35.4",
+ },
+ },
+ "invalid": {
+ "summary": "Invalid data is rejected with an error",
+ "value": {
+ "name": "Baz",
+ "price": "thirty five point four",
+ },
+ },
+ },
+ ),
+ ],
+):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs_src/schema_extra_example/tutorial004_an_py310.py b/docs_src/schema_extra_example/tutorial004_an_py310.py
new file mode 100644
index 000000000..01f1a486c
--- /dev/null
+++ b/docs_src/schema_extra_example/tutorial004_an_py310.py
@@ -0,0 +1,54 @@
+from typing import Annotated
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: str | None = None
+ price: float
+ tax: float | None = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(
+ *,
+ item_id: int,
+ item: Annotated[
+ Item,
+ Body(
+ examples={
+ "normal": {
+ "summary": "A normal example",
+ "description": "A **normal** item works correctly.",
+ "value": {
+ "name": "Foo",
+ "description": "A very nice Item",
+ "price": 35.4,
+ "tax": 3.2,
+ },
+ },
+ "converted": {
+ "summary": "An example with converted data",
+ "description": "FastAPI can convert price `strings` to actual `numbers` automatically",
+ "value": {
+ "name": "Bar",
+ "price": "35.4",
+ },
+ },
+ "invalid": {
+ "summary": "Invalid data is rejected with an error",
+ "value": {
+ "name": "Baz",
+ "price": "thirty five point four",
+ },
+ },
+ },
+ ),
+ ],
+):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs_src/schema_extra_example/tutorial004_an_py39.py b/docs_src/schema_extra_example/tutorial004_an_py39.py
new file mode 100644
index 000000000..d50e8aa5f
--- /dev/null
+++ b/docs_src/schema_extra_example/tutorial004_an_py39.py
@@ -0,0 +1,54 @@
+from typing import Annotated, Union
+
+from fastapi import Body, FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+ name: str
+ description: Union[str, None] = None
+ price: float
+ tax: Union[float, None] = None
+
+
+@app.put("/items/{item_id}")
+async def update_item(
+ *,
+ item_id: int,
+ item: Annotated[
+ Item,
+ Body(
+ examples={
+ "normal": {
+ "summary": "A normal example",
+ "description": "A **normal** item works correctly.",
+ "value": {
+ "name": "Foo",
+ "description": "A very nice Item",
+ "price": 35.4,
+ "tax": 3.2,
+ },
+ },
+ "converted": {
+ "summary": "An example with converted data",
+ "description": "FastAPI can convert price `strings` to actual `numbers` automatically",
+ "value": {
+ "name": "Bar",
+ "price": "35.4",
+ },
+ },
+ "invalid": {
+ "summary": "Invalid data is rejected with an error",
+ "value": {
+ "name": "Baz",
+ "price": "thirty five point four",
+ },
+ },
+ },
+ ),
+ ],
+):
+ results = {"item_id": item_id, "item": item}
+ return results
diff --git a/docs_src/security/tutorial001_an.py b/docs_src/security/tutorial001_an.py
new file mode 100644
index 000000000..dac915b7c
--- /dev/null
+++ b/docs_src/security/tutorial001_an.py
@@ -0,0 +1,12 @@
+from fastapi import Depends, FastAPI
+from fastapi.security import OAuth2PasswordBearer
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
+
+
+@app.get("/items/")
+async def read_items(token: Annotated[str, Depends(oauth2_scheme)]):
+ return {"token": token}
diff --git a/docs_src/security/tutorial001_an_py39.py b/docs_src/security/tutorial001_an_py39.py
new file mode 100644
index 000000000..de110402e
--- /dev/null
+++ b/docs_src/security/tutorial001_an_py39.py
@@ -0,0 +1,13 @@
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+from fastapi.security import OAuth2PasswordBearer
+
+app = FastAPI()
+
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
+
+
+@app.get("/items/")
+async def read_items(token: Annotated[str, Depends(oauth2_scheme)]):
+ return {"token": token}
diff --git a/docs_src/security/tutorial002_an.py b/docs_src/security/tutorial002_an.py
new file mode 100644
index 000000000..291b3bf53
--- /dev/null
+++ b/docs_src/security/tutorial002_an.py
@@ -0,0 +1,33 @@
+from typing import Union
+
+from fastapi import Depends, FastAPI
+from fastapi.security import OAuth2PasswordBearer
+from pydantic import BaseModel
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
+
+
+class User(BaseModel):
+ username: str
+ email: Union[str, None] = None
+ full_name: Union[str, None] = None
+ disabled: Union[bool, None] = None
+
+
+def fake_decode_token(token):
+ return User(
+ username=token + "fakedecoded", email="john@example.com", full_name="John Doe"
+ )
+
+
+async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
+ user = fake_decode_token(token)
+ return user
+
+
+@app.get("/users/me")
+async def read_users_me(current_user: Annotated[User, Depends(get_current_user)]):
+ return current_user
diff --git a/docs_src/security/tutorial002_an_py310.py b/docs_src/security/tutorial002_an_py310.py
new file mode 100644
index 000000000..c7b761e45
--- /dev/null
+++ b/docs_src/security/tutorial002_an_py310.py
@@ -0,0 +1,32 @@
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+from fastapi.security import OAuth2PasswordBearer
+from pydantic import BaseModel
+
+app = FastAPI()
+
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
+
+
+class User(BaseModel):
+ username: str
+ email: str | None = None
+ full_name: str | None = None
+ disabled: bool | None = None
+
+
+def fake_decode_token(token):
+ return User(
+ username=token + "fakedecoded", email="john@example.com", full_name="John Doe"
+ )
+
+
+async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
+ user = fake_decode_token(token)
+ return user
+
+
+@app.get("/users/me")
+async def read_users_me(current_user: Annotated[User, Depends(get_current_user)]):
+ return current_user
diff --git a/docs_src/security/tutorial002_an_py39.py b/docs_src/security/tutorial002_an_py39.py
new file mode 100644
index 000000000..7ff1c470b
--- /dev/null
+++ b/docs_src/security/tutorial002_an_py39.py
@@ -0,0 +1,32 @@
+from typing import Annotated, Union
+
+from fastapi import Depends, FastAPI
+from fastapi.security import OAuth2PasswordBearer
+from pydantic import BaseModel
+
+app = FastAPI()
+
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
+
+
+class User(BaseModel):
+ username: str
+ email: Union[str, None] = None
+ full_name: Union[str, None] = None
+ disabled: Union[bool, None] = None
+
+
+def fake_decode_token(token):
+ return User(
+ username=token + "fakedecoded", email="john@example.com", full_name="John Doe"
+ )
+
+
+async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
+ user = fake_decode_token(token)
+ return user
+
+
+@app.get("/users/me")
+async def read_users_me(current_user: Annotated[User, Depends(get_current_user)]):
+ return current_user
diff --git a/docs_src/security/tutorial003_an.py b/docs_src/security/tutorial003_an.py
new file mode 100644
index 000000000..261cb4857
--- /dev/null
+++ b/docs_src/security/tutorial003_an.py
@@ -0,0 +1,95 @@
+from typing import Union
+
+from fastapi import Depends, FastAPI, HTTPException, status
+from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
+from pydantic import BaseModel
+from typing_extensions import Annotated
+
+fake_users_db = {
+ "johndoe": {
+ "username": "johndoe",
+ "full_name": "John Doe",
+ "email": "johndoe@example.com",
+ "hashed_password": "fakehashedsecret",
+ "disabled": False,
+ },
+ "alice": {
+ "username": "alice",
+ "full_name": "Alice Wonderson",
+ "email": "alice@example.com",
+ "hashed_password": "fakehashedsecret2",
+ "disabled": True,
+ },
+}
+
+app = FastAPI()
+
+
+def fake_hash_password(password: str):
+ return "fakehashed" + password
+
+
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
+
+
+class User(BaseModel):
+ username: str
+ email: Union[str, None] = None
+ full_name: Union[str, None] = None
+ disabled: Union[bool, None] = None
+
+
+class UserInDB(User):
+ hashed_password: str
+
+
+def get_user(db, username: str):
+ if username in db:
+ user_dict = db[username]
+ return UserInDB(**user_dict)
+
+
+def fake_decode_token(token):
+ # This doesn't provide any security at all
+ # Check the next version
+ user = get_user(fake_users_db, token)
+ return user
+
+
+async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
+ user = fake_decode_token(token)
+ if not user:
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Invalid authentication credentials",
+ headers={"WWW-Authenticate": "Bearer"},
+ )
+ return user
+
+
+async def get_current_active_user(
+ current_user: Annotated[User, Depends(get_current_user)]
+):
+ if current_user.disabled:
+ raise HTTPException(status_code=400, detail="Inactive user")
+ return current_user
+
+
+@app.post("/token")
+async def login(form_data: Annotated[OAuth2PasswordRequestForm, Depends()]):
+ user_dict = fake_users_db.get(form_data.username)
+ if not user_dict:
+ raise HTTPException(status_code=400, detail="Incorrect username or password")
+ user = UserInDB(**user_dict)
+ hashed_password = fake_hash_password(form_data.password)
+ if not hashed_password == user.hashed_password:
+ raise HTTPException(status_code=400, detail="Incorrect username or password")
+
+ return {"access_token": user.username, "token_type": "bearer"}
+
+
+@app.get("/users/me")
+async def read_users_me(
+ current_user: Annotated[User, Depends(get_current_active_user)]
+):
+ return current_user
diff --git a/docs_src/security/tutorial003_an_py310.py b/docs_src/security/tutorial003_an_py310.py
new file mode 100644
index 000000000..a03f4f8bf
--- /dev/null
+++ b/docs_src/security/tutorial003_an_py310.py
@@ -0,0 +1,94 @@
+from typing import Annotated
+
+from fastapi import Depends, FastAPI, HTTPException, status
+from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
+from pydantic import BaseModel
+
+fake_users_db = {
+ "johndoe": {
+ "username": "johndoe",
+ "full_name": "John Doe",
+ "email": "johndoe@example.com",
+ "hashed_password": "fakehashedsecret",
+ "disabled": False,
+ },
+ "alice": {
+ "username": "alice",
+ "full_name": "Alice Wonderson",
+ "email": "alice@example.com",
+ "hashed_password": "fakehashedsecret2",
+ "disabled": True,
+ },
+}
+
+app = FastAPI()
+
+
+def fake_hash_password(password: str):
+ return "fakehashed" + password
+
+
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
+
+
+class User(BaseModel):
+ username: str
+ email: str | None = None
+ full_name: str | None = None
+ disabled: bool | None = None
+
+
+class UserInDB(User):
+ hashed_password: str
+
+
+def get_user(db, username: str):
+ if username in db:
+ user_dict = db[username]
+ return UserInDB(**user_dict)
+
+
+def fake_decode_token(token):
+ # This doesn't provide any security at all
+ # Check the next version
+ user = get_user(fake_users_db, token)
+ return user
+
+
+async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
+ user = fake_decode_token(token)
+ if not user:
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Invalid authentication credentials",
+ headers={"WWW-Authenticate": "Bearer"},
+ )
+ return user
+
+
+async def get_current_active_user(
+ current_user: Annotated[User, Depends(get_current_user)]
+):
+ if current_user.disabled:
+ raise HTTPException(status_code=400, detail="Inactive user")
+ return current_user
+
+
+@app.post("/token")
+async def login(form_data: Annotated[OAuth2PasswordRequestForm, Depends()]):
+ user_dict = fake_users_db.get(form_data.username)
+ if not user_dict:
+ raise HTTPException(status_code=400, detail="Incorrect username or password")
+ user = UserInDB(**user_dict)
+ hashed_password = fake_hash_password(form_data.password)
+ if not hashed_password == user.hashed_password:
+ raise HTTPException(status_code=400, detail="Incorrect username or password")
+
+ return {"access_token": user.username, "token_type": "bearer"}
+
+
+@app.get("/users/me")
+async def read_users_me(
+ current_user: Annotated[User, Depends(get_current_active_user)]
+):
+ return current_user
diff --git a/docs_src/security/tutorial003_an_py39.py b/docs_src/security/tutorial003_an_py39.py
new file mode 100644
index 000000000..308dbe798
--- /dev/null
+++ b/docs_src/security/tutorial003_an_py39.py
@@ -0,0 +1,94 @@
+from typing import Annotated, Union
+
+from fastapi import Depends, FastAPI, HTTPException, status
+from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
+from pydantic import BaseModel
+
+fake_users_db = {
+ "johndoe": {
+ "username": "johndoe",
+ "full_name": "John Doe",
+ "email": "johndoe@example.com",
+ "hashed_password": "fakehashedsecret",
+ "disabled": False,
+ },
+ "alice": {
+ "username": "alice",
+ "full_name": "Alice Wonderson",
+ "email": "alice@example.com",
+ "hashed_password": "fakehashedsecret2",
+ "disabled": True,
+ },
+}
+
+app = FastAPI()
+
+
+def fake_hash_password(password: str):
+ return "fakehashed" + password
+
+
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
+
+
+class User(BaseModel):
+ username: str
+ email: Union[str, None] = None
+ full_name: Union[str, None] = None
+ disabled: Union[bool, None] = None
+
+
+class UserInDB(User):
+ hashed_password: str
+
+
+def get_user(db, username: str):
+ if username in db:
+ user_dict = db[username]
+ return UserInDB(**user_dict)
+
+
+def fake_decode_token(token):
+ # This doesn't provide any security at all
+ # Check the next version
+ user = get_user(fake_users_db, token)
+ return user
+
+
+async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
+ user = fake_decode_token(token)
+ if not user:
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Invalid authentication credentials",
+ headers={"WWW-Authenticate": "Bearer"},
+ )
+ return user
+
+
+async def get_current_active_user(
+ current_user: Annotated[User, Depends(get_current_user)]
+):
+ if current_user.disabled:
+ raise HTTPException(status_code=400, detail="Inactive user")
+ return current_user
+
+
+@app.post("/token")
+async def login(form_data: Annotated[OAuth2PasswordRequestForm, Depends()]):
+ user_dict = fake_users_db.get(form_data.username)
+ if not user_dict:
+ raise HTTPException(status_code=400, detail="Incorrect username or password")
+ user = UserInDB(**user_dict)
+ hashed_password = fake_hash_password(form_data.password)
+ if not hashed_password == user.hashed_password:
+ raise HTTPException(status_code=400, detail="Incorrect username or password")
+
+ return {"access_token": user.username, "token_type": "bearer"}
+
+
+@app.get("/users/me")
+async def read_users_me(
+ current_user: Annotated[User, Depends(get_current_active_user)]
+):
+ return current_user
diff --git a/docs_src/security/tutorial004_an.py b/docs_src/security/tutorial004_an.py
new file mode 100644
index 000000000..ca350343d
--- /dev/null
+++ b/docs_src/security/tutorial004_an.py
@@ -0,0 +1,147 @@
+from datetime import datetime, timedelta
+from typing import Union
+
+from fastapi import Depends, FastAPI, HTTPException, status
+from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
+from jose import JWTError, jwt
+from passlib.context import CryptContext
+from pydantic import BaseModel
+from typing_extensions import Annotated
+
+# to get a string like this run:
+# openssl rand -hex 32
+SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
+ALGORITHM = "HS256"
+ACCESS_TOKEN_EXPIRE_MINUTES = 30
+
+
+fake_users_db = {
+ "johndoe": {
+ "username": "johndoe",
+ "full_name": "John Doe",
+ "email": "johndoe@example.com",
+ "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
+ "disabled": False,
+ }
+}
+
+
+class Token(BaseModel):
+ access_token: str
+ token_type: str
+
+
+class TokenData(BaseModel):
+ username: Union[str, None] = None
+
+
+class User(BaseModel):
+ username: str
+ email: Union[str, None] = None
+ full_name: Union[str, None] = None
+ disabled: Union[bool, None] = None
+
+
+class UserInDB(User):
+ hashed_password: str
+
+
+pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
+
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
+
+app = FastAPI()
+
+
+def verify_password(plain_password, hashed_password):
+ return pwd_context.verify(plain_password, hashed_password)
+
+
+def get_password_hash(password):
+ return pwd_context.hash(password)
+
+
+def get_user(db, username: str):
+ if username in db:
+ user_dict = db[username]
+ return UserInDB(**user_dict)
+
+
+def authenticate_user(fake_db, username: str, password: str):
+ user = get_user(fake_db, username)
+ if not user:
+ return False
+ if not verify_password(password, user.hashed_password):
+ return False
+ return user
+
+
+def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
+ to_encode = data.copy()
+ if expires_delta:
+ expire = datetime.utcnow() + expires_delta
+ else:
+ expire = datetime.utcnow() + timedelta(minutes=15)
+ to_encode.update({"exp": expire})
+ encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
+ return encoded_jwt
+
+
+async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
+ credentials_exception = HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Could not validate credentials",
+ headers={"WWW-Authenticate": "Bearer"},
+ )
+ try:
+ payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
+ username: str = payload.get("sub")
+ if username is None:
+ raise credentials_exception
+ token_data = TokenData(username=username)
+ except JWTError:
+ raise credentials_exception
+ user = get_user(fake_users_db, username=token_data.username)
+ if user is None:
+ raise credentials_exception
+ return user
+
+
+async def get_current_active_user(
+ current_user: Annotated[User, Depends(get_current_user)]
+):
+ if current_user.disabled:
+ raise HTTPException(status_code=400, detail="Inactive user")
+ return current_user
+
+
+@app.post("/token", response_model=Token)
+async def login_for_access_token(
+ form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
+):
+ user = authenticate_user(fake_users_db, form_data.username, form_data.password)
+ if not user:
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Incorrect username or password",
+ headers={"WWW-Authenticate": "Bearer"},
+ )
+ access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
+ access_token = create_access_token(
+ data={"sub": user.username}, expires_delta=access_token_expires
+ )
+ return {"access_token": access_token, "token_type": "bearer"}
+
+
+@app.get("/users/me/", response_model=User)
+async def read_users_me(
+ current_user: Annotated[User, Depends(get_current_active_user)]
+):
+ return current_user
+
+
+@app.get("/users/me/items/")
+async def read_own_items(
+ current_user: Annotated[User, Depends(get_current_active_user)]
+):
+ return [{"item_id": "Foo", "owner": current_user.username}]
diff --git a/docs_src/security/tutorial004_an_py310.py b/docs_src/security/tutorial004_an_py310.py
new file mode 100644
index 000000000..8bf5f3b71
--- /dev/null
+++ b/docs_src/security/tutorial004_an_py310.py
@@ -0,0 +1,146 @@
+from datetime import datetime, timedelta
+from typing import Annotated
+
+from fastapi import Depends, FastAPI, HTTPException, status
+from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
+from jose import JWTError, jwt
+from passlib.context import CryptContext
+from pydantic import BaseModel
+
+# to get a string like this run:
+# openssl rand -hex 32
+SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
+ALGORITHM = "HS256"
+ACCESS_TOKEN_EXPIRE_MINUTES = 30
+
+
+fake_users_db = {
+ "johndoe": {
+ "username": "johndoe",
+ "full_name": "John Doe",
+ "email": "johndoe@example.com",
+ "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
+ "disabled": False,
+ }
+}
+
+
+class Token(BaseModel):
+ access_token: str
+ token_type: str
+
+
+class TokenData(BaseModel):
+ username: str | None = None
+
+
+class User(BaseModel):
+ username: str
+ email: str | None = None
+ full_name: str | None = None
+ disabled: bool | None = None
+
+
+class UserInDB(User):
+ hashed_password: str
+
+
+pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
+
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
+
+app = FastAPI()
+
+
+def verify_password(plain_password, hashed_password):
+ return pwd_context.verify(plain_password, hashed_password)
+
+
+def get_password_hash(password):
+ return pwd_context.hash(password)
+
+
+def get_user(db, username: str):
+ if username in db:
+ user_dict = db[username]
+ return UserInDB(**user_dict)
+
+
+def authenticate_user(fake_db, username: str, password: str):
+ user = get_user(fake_db, username)
+ if not user:
+ return False
+ if not verify_password(password, user.hashed_password):
+ return False
+ return user
+
+
+def create_access_token(data: dict, expires_delta: timedelta | None = None):
+ to_encode = data.copy()
+ if expires_delta:
+ expire = datetime.utcnow() + expires_delta
+ else:
+ expire = datetime.utcnow() + timedelta(minutes=15)
+ to_encode.update({"exp": expire})
+ encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
+ return encoded_jwt
+
+
+async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
+ credentials_exception = HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Could not validate credentials",
+ headers={"WWW-Authenticate": "Bearer"},
+ )
+ try:
+ payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
+ username: str = payload.get("sub")
+ if username is None:
+ raise credentials_exception
+ token_data = TokenData(username=username)
+ except JWTError:
+ raise credentials_exception
+ user = get_user(fake_users_db, username=token_data.username)
+ if user is None:
+ raise credentials_exception
+ return user
+
+
+async def get_current_active_user(
+ current_user: Annotated[User, Depends(get_current_user)]
+):
+ if current_user.disabled:
+ raise HTTPException(status_code=400, detail="Inactive user")
+ return current_user
+
+
+@app.post("/token", response_model=Token)
+async def login_for_access_token(
+ form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
+):
+ user = authenticate_user(fake_users_db, form_data.username, form_data.password)
+ if not user:
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Incorrect username or password",
+ headers={"WWW-Authenticate": "Bearer"},
+ )
+ access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
+ access_token = create_access_token(
+ data={"sub": user.username}, expires_delta=access_token_expires
+ )
+ return {"access_token": access_token, "token_type": "bearer"}
+
+
+@app.get("/users/me/", response_model=User)
+async def read_users_me(
+ current_user: Annotated[User, Depends(get_current_active_user)]
+):
+ return current_user
+
+
+@app.get("/users/me/items/")
+async def read_own_items(
+ current_user: Annotated[User, Depends(get_current_active_user)]
+):
+ return [{"item_id": "Foo", "owner": current_user.username}]
diff --git a/docs_src/security/tutorial004_an_py39.py b/docs_src/security/tutorial004_an_py39.py
new file mode 100644
index 000000000..a634e23de
--- /dev/null
+++ b/docs_src/security/tutorial004_an_py39.py
@@ -0,0 +1,146 @@
+from datetime import datetime, timedelta
+from typing import Annotated, Union
+
+from fastapi import Depends, FastAPI, HTTPException, status
+from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
+from jose import JWTError, jwt
+from passlib.context import CryptContext
+from pydantic import BaseModel
+
+# to get a string like this run:
+# openssl rand -hex 32
+SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
+ALGORITHM = "HS256"
+ACCESS_TOKEN_EXPIRE_MINUTES = 30
+
+
+fake_users_db = {
+ "johndoe": {
+ "username": "johndoe",
+ "full_name": "John Doe",
+ "email": "johndoe@example.com",
+ "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
+ "disabled": False,
+ }
+}
+
+
+class Token(BaseModel):
+ access_token: str
+ token_type: str
+
+
+class TokenData(BaseModel):
+ username: Union[str, None] = None
+
+
+class User(BaseModel):
+ username: str
+ email: Union[str, None] = None
+ full_name: Union[str, None] = None
+ disabled: Union[bool, None] = None
+
+
+class UserInDB(User):
+ hashed_password: str
+
+
+pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
+
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
+
+app = FastAPI()
+
+
+def verify_password(plain_password, hashed_password):
+ return pwd_context.verify(plain_password, hashed_password)
+
+
+def get_password_hash(password):
+ return pwd_context.hash(password)
+
+
+def get_user(db, username: str):
+ if username in db:
+ user_dict = db[username]
+ return UserInDB(**user_dict)
+
+
+def authenticate_user(fake_db, username: str, password: str):
+ user = get_user(fake_db, username)
+ if not user:
+ return False
+ if not verify_password(password, user.hashed_password):
+ return False
+ return user
+
+
+def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
+ to_encode = data.copy()
+ if expires_delta:
+ expire = datetime.utcnow() + expires_delta
+ else:
+ expire = datetime.utcnow() + timedelta(minutes=15)
+ to_encode.update({"exp": expire})
+ encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
+ return encoded_jwt
+
+
+async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
+ credentials_exception = HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Could not validate credentials",
+ headers={"WWW-Authenticate": "Bearer"},
+ )
+ try:
+ payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
+ username: str = payload.get("sub")
+ if username is None:
+ raise credentials_exception
+ token_data = TokenData(username=username)
+ except JWTError:
+ raise credentials_exception
+ user = get_user(fake_users_db, username=token_data.username)
+ if user is None:
+ raise credentials_exception
+ return user
+
+
+async def get_current_active_user(
+ current_user: Annotated[User, Depends(get_current_user)]
+):
+ if current_user.disabled:
+ raise HTTPException(status_code=400, detail="Inactive user")
+ return current_user
+
+
+@app.post("/token", response_model=Token)
+async def login_for_access_token(
+ form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
+):
+ user = authenticate_user(fake_users_db, form_data.username, form_data.password)
+ if not user:
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Incorrect username or password",
+ headers={"WWW-Authenticate": "Bearer"},
+ )
+ access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
+ access_token = create_access_token(
+ data={"sub": user.username}, expires_delta=access_token_expires
+ )
+ return {"access_token": access_token, "token_type": "bearer"}
+
+
+@app.get("/users/me/", response_model=User)
+async def read_users_me(
+ current_user: Annotated[User, Depends(get_current_active_user)]
+):
+ return current_user
+
+
+@app.get("/users/me/items/")
+async def read_own_items(
+ current_user: Annotated[User, Depends(get_current_active_user)]
+):
+ return [{"item_id": "Foo", "owner": current_user.username}]
diff --git a/docs_src/security/tutorial005_an.py b/docs_src/security/tutorial005_an.py
new file mode 100644
index 000000000..ec4fa1a07
--- /dev/null
+++ b/docs_src/security/tutorial005_an.py
@@ -0,0 +1,178 @@
+from datetime import datetime, timedelta
+from typing import List, Union
+
+from fastapi import Depends, FastAPI, HTTPException, Security, status
+from fastapi.security import (
+ OAuth2PasswordBearer,
+ OAuth2PasswordRequestForm,
+ SecurityScopes,
+)
+from jose import JWTError, jwt
+from passlib.context import CryptContext
+from pydantic import BaseModel, ValidationError
+from typing_extensions import Annotated
+
+# to get a string like this run:
+# openssl rand -hex 32
+SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
+ALGORITHM = "HS256"
+ACCESS_TOKEN_EXPIRE_MINUTES = 30
+
+
+fake_users_db = {
+ "johndoe": {
+ "username": "johndoe",
+ "full_name": "John Doe",
+ "email": "johndoe@example.com",
+ "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
+ "disabled": False,
+ },
+ "alice": {
+ "username": "alice",
+ "full_name": "Alice Chains",
+ "email": "alicechains@example.com",
+ "hashed_password": "$2b$12$gSvqqUPvlXP2tfVFaWK1Be7DlH.PKZbv5H8KnzzVgXXbVxpva.pFm",
+ "disabled": True,
+ },
+}
+
+
+class Token(BaseModel):
+ access_token: str
+ token_type: str
+
+
+class TokenData(BaseModel):
+ username: Union[str, None] = None
+ scopes: List[str] = []
+
+
+class User(BaseModel):
+ username: str
+ email: Union[str, None] = None
+ full_name: Union[str, None] = None
+ disabled: Union[bool, None] = None
+
+
+class UserInDB(User):
+ hashed_password: str
+
+
+pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
+
+oauth2_scheme = OAuth2PasswordBearer(
+ tokenUrl="token",
+ scopes={"me": "Read information about the current user.", "items": "Read items."},
+)
+
+app = FastAPI()
+
+
+def verify_password(plain_password, hashed_password):
+ return pwd_context.verify(plain_password, hashed_password)
+
+
+def get_password_hash(password):
+ return pwd_context.hash(password)
+
+
+def get_user(db, username: str):
+ if username in db:
+ user_dict = db[username]
+ return UserInDB(**user_dict)
+
+
+def authenticate_user(fake_db, username: str, password: str):
+ user = get_user(fake_db, username)
+ if not user:
+ return False
+ if not verify_password(password, user.hashed_password):
+ return False
+ return user
+
+
+def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
+ to_encode = data.copy()
+ if expires_delta:
+ expire = datetime.utcnow() + expires_delta
+ else:
+ expire = datetime.utcnow() + timedelta(minutes=15)
+ to_encode.update({"exp": expire})
+ encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
+ return encoded_jwt
+
+
+async def get_current_user(
+ security_scopes: SecurityScopes, token: Annotated[str, Depends(oauth2_scheme)]
+):
+ if security_scopes.scopes:
+ authenticate_value = f'Bearer scope="{security_scopes.scope_str}"'
+ else:
+ authenticate_value = "Bearer"
+ credentials_exception = HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Could not validate credentials",
+ headers={"WWW-Authenticate": authenticate_value},
+ )
+ try:
+ payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
+ username: str = payload.get("sub")
+ if username is None:
+ raise credentials_exception
+ token_scopes = payload.get("scopes", [])
+ token_data = TokenData(scopes=token_scopes, username=username)
+ except (JWTError, ValidationError):
+ raise credentials_exception
+ user = get_user(fake_users_db, username=token_data.username)
+ if user is None:
+ raise credentials_exception
+ for scope in security_scopes.scopes:
+ if scope not in token_data.scopes:
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Not enough permissions",
+ headers={"WWW-Authenticate": authenticate_value},
+ )
+ return user
+
+
+async def get_current_active_user(
+ current_user: Annotated[User, Security(get_current_user, scopes=["me"])]
+):
+ if current_user.disabled:
+ raise HTTPException(status_code=400, detail="Inactive user")
+ return current_user
+
+
+@app.post("/token", response_model=Token)
+async def login_for_access_token(
+ form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
+):
+ user = authenticate_user(fake_users_db, form_data.username, form_data.password)
+ if not user:
+ raise HTTPException(status_code=400, detail="Incorrect username or password")
+ access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
+ access_token = create_access_token(
+ data={"sub": user.username, "scopes": form_data.scopes},
+ expires_delta=access_token_expires,
+ )
+ return {"access_token": access_token, "token_type": "bearer"}
+
+
+@app.get("/users/me/", response_model=User)
+async def read_users_me(
+ current_user: Annotated[User, Depends(get_current_active_user)]
+):
+ return current_user
+
+
+@app.get("/users/me/items/")
+async def read_own_items(
+ current_user: Annotated[User, Security(get_current_active_user, scopes=["items"])]
+):
+ return [{"item_id": "Foo", "owner": current_user.username}]
+
+
+@app.get("/status/")
+async def read_system_status(current_user: Annotated[User, Depends(get_current_user)]):
+ return {"status": "ok"}
diff --git a/docs_src/security/tutorial005_an_py310.py b/docs_src/security/tutorial005_an_py310.py
new file mode 100644
index 000000000..45f3fc0bd
--- /dev/null
+++ b/docs_src/security/tutorial005_an_py310.py
@@ -0,0 +1,177 @@
+from datetime import datetime, timedelta
+from typing import Annotated
+
+from fastapi import Depends, FastAPI, HTTPException, Security, status
+from fastapi.security import (
+ OAuth2PasswordBearer,
+ OAuth2PasswordRequestForm,
+ SecurityScopes,
+)
+from jose import JWTError, jwt
+from passlib.context import CryptContext
+from pydantic import BaseModel, ValidationError
+
+# to get a string like this run:
+# openssl rand -hex 32
+SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
+ALGORITHM = "HS256"
+ACCESS_TOKEN_EXPIRE_MINUTES = 30
+
+
+fake_users_db = {
+ "johndoe": {
+ "username": "johndoe",
+ "full_name": "John Doe",
+ "email": "johndoe@example.com",
+ "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
+ "disabled": False,
+ },
+ "alice": {
+ "username": "alice",
+ "full_name": "Alice Chains",
+ "email": "alicechains@example.com",
+ "hashed_password": "$2b$12$gSvqqUPvlXP2tfVFaWK1Be7DlH.PKZbv5H8KnzzVgXXbVxpva.pFm",
+ "disabled": True,
+ },
+}
+
+
+class Token(BaseModel):
+ access_token: str
+ token_type: str
+
+
+class TokenData(BaseModel):
+ username: str | None = None
+ scopes: list[str] = []
+
+
+class User(BaseModel):
+ username: str
+ email: str | None = None
+ full_name: str | None = None
+ disabled: bool | None = None
+
+
+class UserInDB(User):
+ hashed_password: str
+
+
+pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
+
+oauth2_scheme = OAuth2PasswordBearer(
+ tokenUrl="token",
+ scopes={"me": "Read information about the current user.", "items": "Read items."},
+)
+
+app = FastAPI()
+
+
+def verify_password(plain_password, hashed_password):
+ return pwd_context.verify(plain_password, hashed_password)
+
+
+def get_password_hash(password):
+ return pwd_context.hash(password)
+
+
+def get_user(db, username: str):
+ if username in db:
+ user_dict = db[username]
+ return UserInDB(**user_dict)
+
+
+def authenticate_user(fake_db, username: str, password: str):
+ user = get_user(fake_db, username)
+ if not user:
+ return False
+ if not verify_password(password, user.hashed_password):
+ return False
+ return user
+
+
+def create_access_token(data: dict, expires_delta: timedelta | None = None):
+ to_encode = data.copy()
+ if expires_delta:
+ expire = datetime.utcnow() + expires_delta
+ else:
+ expire = datetime.utcnow() + timedelta(minutes=15)
+ to_encode.update({"exp": expire})
+ encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
+ return encoded_jwt
+
+
+async def get_current_user(
+ security_scopes: SecurityScopes, token: Annotated[str, Depends(oauth2_scheme)]
+):
+ if security_scopes.scopes:
+ authenticate_value = f'Bearer scope="{security_scopes.scope_str}"'
+ else:
+ authenticate_value = "Bearer"
+ credentials_exception = HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Could not validate credentials",
+ headers={"WWW-Authenticate": authenticate_value},
+ )
+ try:
+ payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
+ username: str = payload.get("sub")
+ if username is None:
+ raise credentials_exception
+ token_scopes = payload.get("scopes", [])
+ token_data = TokenData(scopes=token_scopes, username=username)
+ except (JWTError, ValidationError):
+ raise credentials_exception
+ user = get_user(fake_users_db, username=token_data.username)
+ if user is None:
+ raise credentials_exception
+ for scope in security_scopes.scopes:
+ if scope not in token_data.scopes:
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Not enough permissions",
+ headers={"WWW-Authenticate": authenticate_value},
+ )
+ return user
+
+
+async def get_current_active_user(
+ current_user: Annotated[User, Security(get_current_user, scopes=["me"])]
+):
+ if current_user.disabled:
+ raise HTTPException(status_code=400, detail="Inactive user")
+ return current_user
+
+
+@app.post("/token", response_model=Token)
+async def login_for_access_token(
+ form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
+):
+ user = authenticate_user(fake_users_db, form_data.username, form_data.password)
+ if not user:
+ raise HTTPException(status_code=400, detail="Incorrect username or password")
+ access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
+ access_token = create_access_token(
+ data={"sub": user.username, "scopes": form_data.scopes},
+ expires_delta=access_token_expires,
+ )
+ return {"access_token": access_token, "token_type": "bearer"}
+
+
+@app.get("/users/me/", response_model=User)
+async def read_users_me(
+ current_user: Annotated[User, Depends(get_current_active_user)]
+):
+ return current_user
+
+
+@app.get("/users/me/items/")
+async def read_own_items(
+ current_user: Annotated[User, Security(get_current_active_user, scopes=["items"])]
+):
+ return [{"item_id": "Foo", "owner": current_user.username}]
+
+
+@app.get("/status/")
+async def read_system_status(current_user: Annotated[User, Depends(get_current_user)]):
+ return {"status": "ok"}
diff --git a/docs_src/security/tutorial005_an_py39.py b/docs_src/security/tutorial005_an_py39.py
new file mode 100644
index 000000000..ecb5ed516
--- /dev/null
+++ b/docs_src/security/tutorial005_an_py39.py
@@ -0,0 +1,177 @@
+from datetime import datetime, timedelta
+from typing import Annotated, List, Union
+
+from fastapi import Depends, FastAPI, HTTPException, Security, status
+from fastapi.security import (
+ OAuth2PasswordBearer,
+ OAuth2PasswordRequestForm,
+ SecurityScopes,
+)
+from jose import JWTError, jwt
+from passlib.context import CryptContext
+from pydantic import BaseModel, ValidationError
+
+# to get a string like this run:
+# openssl rand -hex 32
+SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
+ALGORITHM = "HS256"
+ACCESS_TOKEN_EXPIRE_MINUTES = 30
+
+
+fake_users_db = {
+ "johndoe": {
+ "username": "johndoe",
+ "full_name": "John Doe",
+ "email": "johndoe@example.com",
+ "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
+ "disabled": False,
+ },
+ "alice": {
+ "username": "alice",
+ "full_name": "Alice Chains",
+ "email": "alicechains@example.com",
+ "hashed_password": "$2b$12$gSvqqUPvlXP2tfVFaWK1Be7DlH.PKZbv5H8KnzzVgXXbVxpva.pFm",
+ "disabled": True,
+ },
+}
+
+
+class Token(BaseModel):
+ access_token: str
+ token_type: str
+
+
+class TokenData(BaseModel):
+ username: Union[str, None] = None
+ scopes: List[str] = []
+
+
+class User(BaseModel):
+ username: str
+ email: Union[str, None] = None
+ full_name: Union[str, None] = None
+ disabled: Union[bool, None] = None
+
+
+class UserInDB(User):
+ hashed_password: str
+
+
+pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
+
+oauth2_scheme = OAuth2PasswordBearer(
+ tokenUrl="token",
+ scopes={"me": "Read information about the current user.", "items": "Read items."},
+)
+
+app = FastAPI()
+
+
+def verify_password(plain_password, hashed_password):
+ return pwd_context.verify(plain_password, hashed_password)
+
+
+def get_password_hash(password):
+ return pwd_context.hash(password)
+
+
+def get_user(db, username: str):
+ if username in db:
+ user_dict = db[username]
+ return UserInDB(**user_dict)
+
+
+def authenticate_user(fake_db, username: str, password: str):
+ user = get_user(fake_db, username)
+ if not user:
+ return False
+ if not verify_password(password, user.hashed_password):
+ return False
+ return user
+
+
+def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
+ to_encode = data.copy()
+ if expires_delta:
+ expire = datetime.utcnow() + expires_delta
+ else:
+ expire = datetime.utcnow() + timedelta(minutes=15)
+ to_encode.update({"exp": expire})
+ encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
+ return encoded_jwt
+
+
+async def get_current_user(
+ security_scopes: SecurityScopes, token: Annotated[str, Depends(oauth2_scheme)]
+):
+ if security_scopes.scopes:
+ authenticate_value = f'Bearer scope="{security_scopes.scope_str}"'
+ else:
+ authenticate_value = "Bearer"
+ credentials_exception = HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Could not validate credentials",
+ headers={"WWW-Authenticate": authenticate_value},
+ )
+ try:
+ payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
+ username: str = payload.get("sub")
+ if username is None:
+ raise credentials_exception
+ token_scopes = payload.get("scopes", [])
+ token_data = TokenData(scopes=token_scopes, username=username)
+ except (JWTError, ValidationError):
+ raise credentials_exception
+ user = get_user(fake_users_db, username=token_data.username)
+ if user is None:
+ raise credentials_exception
+ for scope in security_scopes.scopes:
+ if scope not in token_data.scopes:
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Not enough permissions",
+ headers={"WWW-Authenticate": authenticate_value},
+ )
+ return user
+
+
+async def get_current_active_user(
+ current_user: Annotated[User, Security(get_current_user, scopes=["me"])]
+):
+ if current_user.disabled:
+ raise HTTPException(status_code=400, detail="Inactive user")
+ return current_user
+
+
+@app.post("/token", response_model=Token)
+async def login_for_access_token(
+ form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
+):
+ user = authenticate_user(fake_users_db, form_data.username, form_data.password)
+ if not user:
+ raise HTTPException(status_code=400, detail="Incorrect username or password")
+ access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
+ access_token = create_access_token(
+ data={"sub": user.username, "scopes": form_data.scopes},
+ expires_delta=access_token_expires,
+ )
+ return {"access_token": access_token, "token_type": "bearer"}
+
+
+@app.get("/users/me/", response_model=User)
+async def read_users_me(
+ current_user: Annotated[User, Depends(get_current_active_user)]
+):
+ return current_user
+
+
+@app.get("/users/me/items/")
+async def read_own_items(
+ current_user: Annotated[User, Security(get_current_active_user, scopes=["items"])]
+):
+ return [{"item_id": "Foo", "owner": current_user.username}]
+
+
+@app.get("/status/")
+async def read_system_status(current_user: Annotated[User, Depends(get_current_user)]):
+ return {"status": "ok"}
diff --git a/docs_src/security/tutorial006_an.py b/docs_src/security/tutorial006_an.py
new file mode 100644
index 000000000..985e4b2ad
--- /dev/null
+++ b/docs_src/security/tutorial006_an.py
@@ -0,0 +1,12 @@
+from fastapi import Depends, FastAPI
+from fastapi.security import HTTPBasic, HTTPBasicCredentials
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+security = HTTPBasic()
+
+
+@app.get("/users/me")
+def read_current_user(credentials: Annotated[HTTPBasicCredentials, Depends(security)]):
+ return {"username": credentials.username, "password": credentials.password}
diff --git a/docs_src/security/tutorial006_an_py39.py b/docs_src/security/tutorial006_an_py39.py
new file mode 100644
index 000000000..03c696a4b
--- /dev/null
+++ b/docs_src/security/tutorial006_an_py39.py
@@ -0,0 +1,13 @@
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+from fastapi.security import HTTPBasic, HTTPBasicCredentials
+
+app = FastAPI()
+
+security = HTTPBasic()
+
+
+@app.get("/users/me")
+def read_current_user(credentials: Annotated[HTTPBasicCredentials, Depends(security)]):
+ return {"username": credentials.username, "password": credentials.password}
diff --git a/docs_src/security/tutorial007_an.py b/docs_src/security/tutorial007_an.py
new file mode 100644
index 000000000..5fb7c8e57
--- /dev/null
+++ b/docs_src/security/tutorial007_an.py
@@ -0,0 +1,36 @@
+import secrets
+
+from fastapi import Depends, FastAPI, HTTPException, status
+from fastapi.security import HTTPBasic, HTTPBasicCredentials
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+security = HTTPBasic()
+
+
+def get_current_username(
+ credentials: Annotated[HTTPBasicCredentials, Depends(security)]
+):
+ current_username_bytes = credentials.username.encode("utf8")
+ correct_username_bytes = b"stanleyjobson"
+ is_correct_username = secrets.compare_digest(
+ current_username_bytes, correct_username_bytes
+ )
+ current_password_bytes = credentials.password.encode("utf8")
+ correct_password_bytes = b"swordfish"
+ is_correct_password = secrets.compare_digest(
+ current_password_bytes, correct_password_bytes
+ )
+ if not (is_correct_username and is_correct_password):
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Incorrect email or password",
+ headers={"WWW-Authenticate": "Basic"},
+ )
+ return credentials.username
+
+
+@app.get("/users/me")
+def read_current_user(username: Annotated[str, Depends(get_current_username)]):
+ return {"username": username}
diff --git a/docs_src/security/tutorial007_an_py39.py b/docs_src/security/tutorial007_an_py39.py
new file mode 100644
index 000000000..17177dabf
--- /dev/null
+++ b/docs_src/security/tutorial007_an_py39.py
@@ -0,0 +1,36 @@
+import secrets
+from typing import Annotated
+
+from fastapi import Depends, FastAPI, HTTPException, status
+from fastapi.security import HTTPBasic, HTTPBasicCredentials
+
+app = FastAPI()
+
+security = HTTPBasic()
+
+
+def get_current_username(
+ credentials: Annotated[HTTPBasicCredentials, Depends(security)]
+):
+ current_username_bytes = credentials.username.encode("utf8")
+ correct_username_bytes = b"stanleyjobson"
+ is_correct_username = secrets.compare_digest(
+ current_username_bytes, correct_username_bytes
+ )
+ current_password_bytes = credentials.password.encode("utf8")
+ correct_password_bytes = b"swordfish"
+ is_correct_password = secrets.compare_digest(
+ current_password_bytes, correct_password_bytes
+ )
+ if not (is_correct_username and is_correct_password):
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Incorrect email or password",
+ headers={"WWW-Authenticate": "Basic"},
+ )
+ return credentials.username
+
+
+@app.get("/users/me")
+def read_current_user(username: Annotated[str, Depends(get_current_username)]):
+ return {"username": username}
diff --git a/docs_src/settings/app02_an/__init__.py b/docs_src/settings/app02_an/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs_src/settings/app02_an/config.py b/docs_src/settings/app02_an/config.py
new file mode 100644
index 000000000..9a7829135
--- /dev/null
+++ b/docs_src/settings/app02_an/config.py
@@ -0,0 +1,7 @@
+from pydantic import BaseSettings
+
+
+class Settings(BaseSettings):
+ app_name: str = "Awesome API"
+ admin_email: str
+ items_per_user: int = 50
diff --git a/docs_src/settings/app02_an/main.py b/docs_src/settings/app02_an/main.py
new file mode 100644
index 000000000..cb679202d
--- /dev/null
+++ b/docs_src/settings/app02_an/main.py
@@ -0,0 +1,22 @@
+from functools import lru_cache
+
+from fastapi import Depends, FastAPI
+from typing_extensions import Annotated
+
+from .config import Settings
+
+app = FastAPI()
+
+
+@lru_cache()
+def get_settings():
+ return Settings()
+
+
+@app.get("/info")
+async def info(settings: Annotated[Settings, Depends(get_settings)]):
+ return {
+ "app_name": settings.app_name,
+ "admin_email": settings.admin_email,
+ "items_per_user": settings.items_per_user,
+ }
diff --git a/docs_src/settings/app02_an/test_main.py b/docs_src/settings/app02_an/test_main.py
new file mode 100644
index 000000000..7a04d7e8e
--- /dev/null
+++ b/docs_src/settings/app02_an/test_main.py
@@ -0,0 +1,23 @@
+from fastapi.testclient import TestClient
+
+from .config import Settings
+from .main import app, get_settings
+
+client = TestClient(app)
+
+
+def get_settings_override():
+ return Settings(admin_email="testing_admin@example.com")
+
+
+app.dependency_overrides[get_settings] = get_settings_override
+
+
+def test_app():
+ response = client.get("/info")
+ data = response.json()
+ assert data == {
+ "app_name": "Awesome API",
+ "admin_email": "testing_admin@example.com",
+ "items_per_user": 50,
+ }
diff --git a/docs_src/settings/app02_an_py39/__init__.py b/docs_src/settings/app02_an_py39/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs_src/settings/app02_an_py39/config.py b/docs_src/settings/app02_an_py39/config.py
new file mode 100644
index 000000000..9a7829135
--- /dev/null
+++ b/docs_src/settings/app02_an_py39/config.py
@@ -0,0 +1,7 @@
+from pydantic import BaseSettings
+
+
+class Settings(BaseSettings):
+ app_name: str = "Awesome API"
+ admin_email: str
+ items_per_user: int = 50
diff --git a/docs_src/settings/app02_an_py39/main.py b/docs_src/settings/app02_an_py39/main.py
new file mode 100644
index 000000000..61be74fcb
--- /dev/null
+++ b/docs_src/settings/app02_an_py39/main.py
@@ -0,0 +1,22 @@
+from functools import lru_cache
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+
+from .config import Settings
+
+app = FastAPI()
+
+
+@lru_cache()
+def get_settings():
+ return Settings()
+
+
+@app.get("/info")
+async def info(settings: Annotated[Settings, Depends(get_settings)]):
+ return {
+ "app_name": settings.app_name,
+ "admin_email": settings.admin_email,
+ "items_per_user": settings.items_per_user,
+ }
diff --git a/docs_src/settings/app02_an_py39/test_main.py b/docs_src/settings/app02_an_py39/test_main.py
new file mode 100644
index 000000000..7a04d7e8e
--- /dev/null
+++ b/docs_src/settings/app02_an_py39/test_main.py
@@ -0,0 +1,23 @@
+from fastapi.testclient import TestClient
+
+from .config import Settings
+from .main import app, get_settings
+
+client = TestClient(app)
+
+
+def get_settings_override():
+ return Settings(admin_email="testing_admin@example.com")
+
+
+app.dependency_overrides[get_settings] = get_settings_override
+
+
+def test_app():
+ response = client.get("/info")
+ data = response.json()
+ assert data == {
+ "app_name": "Awesome API",
+ "admin_email": "testing_admin@example.com",
+ "items_per_user": 50,
+ }
diff --git a/docs_src/settings/app03_an/__init__.py b/docs_src/settings/app03_an/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs_src/settings/app03_an/config.py b/docs_src/settings/app03_an/config.py
new file mode 100644
index 000000000..e1c3ee300
--- /dev/null
+++ b/docs_src/settings/app03_an/config.py
@@ -0,0 +1,10 @@
+from pydantic import BaseSettings
+
+
+class Settings(BaseSettings):
+ app_name: str = "Awesome API"
+ admin_email: str
+ items_per_user: int = 50
+
+ class Config:
+ env_file = ".env"
diff --git a/docs_src/settings/app03_an/main.py b/docs_src/settings/app03_an/main.py
new file mode 100644
index 000000000..c33b98f47
--- /dev/null
+++ b/docs_src/settings/app03_an/main.py
@@ -0,0 +1,22 @@
+from functools import lru_cache
+from typing import Annotated
+
+from fastapi import Depends, FastAPI
+
+from . import config
+
+app = FastAPI()
+
+
+@lru_cache()
+def get_settings():
+ return config.Settings()
+
+
+@app.get("/info")
+async def info(settings: Annotated[config.Settings, Depends(get_settings)]):
+ return {
+ "app_name": settings.app_name,
+ "admin_email": settings.admin_email,
+ "items_per_user": settings.items_per_user,
+ }
diff --git a/docs_src/settings/app03_an_py39/__init__.py b/docs_src/settings/app03_an_py39/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs_src/settings/app03_an_py39/config.py b/docs_src/settings/app03_an_py39/config.py
new file mode 100644
index 000000000..e1c3ee300
--- /dev/null
+++ b/docs_src/settings/app03_an_py39/config.py
@@ -0,0 +1,10 @@
+from pydantic import BaseSettings
+
+
+class Settings(BaseSettings):
+ app_name: str = "Awesome API"
+ admin_email: str
+ items_per_user: int = 50
+
+ class Config:
+ env_file = ".env"
diff --git a/docs_src/settings/app03_an_py39/main.py b/docs_src/settings/app03_an_py39/main.py
new file mode 100644
index 000000000..b89c6b6cf
--- /dev/null
+++ b/docs_src/settings/app03_an_py39/main.py
@@ -0,0 +1,22 @@
+from functools import lru_cache
+
+from fastapi import Depends, FastAPI
+from typing_extensions import Annotated
+
+from . import config
+
+app = FastAPI()
+
+
+@lru_cache()
+def get_settings():
+ return config.Settings()
+
+
+@app.get("/info")
+async def info(settings: Annotated[config.Settings, Depends(get_settings)]):
+ return {
+ "app_name": settings.app_name,
+ "admin_email": settings.admin_email,
+ "items_per_user": settings.items_per_user,
+ }
diff --git a/docs_src/websockets/tutorial002_an.py b/docs_src/websockets/tutorial002_an.py
new file mode 100644
index 000000000..c838fbd30
--- /dev/null
+++ b/docs_src/websockets/tutorial002_an.py
@@ -0,0 +1,93 @@
+from typing import Union
+
+from fastapi import (
+ Cookie,
+ Depends,
+ FastAPI,
+ Query,
+ WebSocket,
+ WebSocketException,
+ status,
+)
+from fastapi.responses import HTMLResponse
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+html = """
+
+
+
+