-{% for user in people.top_contributors %}
+{% for user in people.top_contributors[:50] %}
-{% for user in people.top_reviewers %}
+{% for user in people.top_translations_reviewers[:50] %}
{% endfor %}
diff --git a/docs/ru/docs/features.md b/docs/ru/docs/features.md
index 97841cc83..110c7d31e 100644
--- a/docs/ru/docs/features.md
+++ b/docs/ru/docs/features.md
@@ -177,7 +177,7 @@ FastAPI включает в себя чрезвычайно простую в и
## Особенности и возможности Pydantic
-**FastAPI** основан на
Pydantic и полностью совместим с ним. Так что, любой дополнительный код Pydantic, который у вас есть, будет также работать.
+**FastAPI** основан на
Pydantic и полностью совместим с ним. Так что, любой дополнительный код Pydantic, который у вас есть, будет также работать.
Включая внешние библиотеки, также основанные на Pydantic, такие как:
ORM'ы,
ODM'ы для баз данных.
@@ -192,8 +192,6 @@ FastAPI включает в себя чрезвычайно простую в и
* Если вы знаете аннотации типов в Python, вы знаете, как использовать Pydantic.
* Прекрасно сочетается с вашими **
IDE/
linter/мозгом**:
* Потому что структуры данных pydantic - это всего лишь экземпляры классов, определённых вами. Автодополнение, проверка кода, mypy и ваша интуиция - всё будет работать с вашими проверенными данными.
-* **Быстродействие**:
- * В
тестовых замерах Pydantic быстрее, чем все другие проверенные библиотеки.
* Проверка **сложных структур**:
* Использование иерархических моделей Pydantic; `List`, `Dict` и т.п. из модуля `typing` (входит в стандартную библиотеку Python).
* Валидаторы позволяют четко и легко определять, проверять и документировать сложные схемы данных в виде JSON Schema.
diff --git a/docs/ru/docs/help-fastapi.md b/docs/ru/docs/help-fastapi.md
index 65ff768d1..3ad3e6fd4 100644
--- a/docs/ru/docs/help-fastapi.md
+++ b/docs/ru/docs/help-fastapi.md
@@ -12,7 +12,7 @@
## Подписаться на новостную рассылку
-Вы можете подписаться на редкую [новостную рассылку **FastAPI и его друзья**](/newsletter/){.internal-link target=_blank} и быть в курсе о:
+Вы можете подписаться на редкую [новостную рассылку **FastAPI и его друзья**](newsletter.md){.internal-link target=_blank} и быть в курсе о:
* Новостях о FastAPI и его друзьях 🚀
* Руководствах 📝
diff --git a/docs/ru/docs/history-design-future.md b/docs/ru/docs/history-design-future.md
index 2a5e428b1..e9572a6d6 100644
--- a/docs/ru/docs/history-design-future.md
+++ b/docs/ru/docs/history-design-future.md
@@ -52,7 +52,7 @@
## Зависимости
-Протестировав несколько вариантов, я решил, что в качестве основы буду использовать
**Pydantic** и его преимущества.
+Протестировав несколько вариантов, я решил, что в качестве основы буду использовать
**Pydantic** и его преимущества.
По моим предложениям был изменён код этого фреймворка, чтобы сделать его полностью совместимым с JSON Schema, поддержать различные способы определения ограничений и улучшить помощь редакторов (проверки типов, автозаполнение).
diff --git a/docs/ru/docs/index.md b/docs/ru/docs/index.md
index 6c99f623d..477567af6 100644
--- a/docs/ru/docs/index.md
+++ b/docs/ru/docs/index.md
@@ -114,7 +114,7 @@ Python 3.8+
FastAPI стоит на плечах гигантов:
*
Starlette для части связанной с вебом.
-*
Pydantic для части связанной с данными.
+*
Pydantic для части связанной с данными.
## Установка
@@ -445,7 +445,7 @@ item: Item
*
HTTPX
- Обязательно, если вы хотите использовать `TestClient`.
*
jinja2
- Обязательно, если вы хотите использовать конфигурацию шаблона по умолчанию.
-*
python-multipart
- Обязательно, если вы хотите поддерживать форму
"парсинга" с помощью `request.form()`.
+*
python-multipart
- Обязательно, если вы хотите поддерживать форму
"парсинга" с помощью `request.form()`.
*
itsdangerous
- Обязательно, для поддержки `SessionMiddleware`.
*
pyyaml
- Обязательно, для поддержки `SchemaGenerator` Starlette (возможно, вам это не нужно с FastAPI).
*
ujson
- Обязательно, если вы хотите использовать `UJSONResponse`.
diff --git a/docs/ru/docs/python-types.md b/docs/ru/docs/python-types.md
index 7523083c8..3c8492c67 100644
--- a/docs/ru/docs/python-types.md
+++ b/docs/ru/docs/python-types.md
@@ -265,7 +265,7 @@ John Doe
## Pydantic-модели
-
Pydantic является Python-библиотекой для выполнения валидации данных.
+
Pydantic является Python-библиотекой для выполнения валидации данных.
Вы объявляете «форму» данных как классы с атрибутами.
@@ -282,7 +282,7 @@ John Doe
```
!!! info
- Чтобы узнать больше о
Pydantic, читайте его документацию.
+ Чтобы узнать больше о
Pydantic, читайте его документацию.
**FastAPI** целиком основан на Pydantic.
diff --git a/docs/ru/docs/tutorial/body-nested-models.md b/docs/ru/docs/tutorial/body-nested-models.md
index bbf9b7685..51a32ba56 100644
--- a/docs/ru/docs/tutorial/body-nested-models.md
+++ b/docs/ru/docs/tutorial/body-nested-models.md
@@ -192,7 +192,7 @@ my_list: List[str]
Помимо обычных простых типов, таких как `str`, `int`, `float`, и т.д. Вы можете использовать более сложные базовые типы, которые наследуются от типа `str`.
-Чтобы увидеть все варианты, которые у вас есть, ознакомьтесь с документацией
по необычным типам Pydantic. Вы увидите некоторые примеры в следующей главе.
+Чтобы увидеть все варианты, которые у вас есть, ознакомьтесь с документацией
по необычным типам Pydantic. Вы увидите некоторые примеры в следующей главе.
Например, так как в модели `Image` у нас есть поле `url`, то мы можем объявить его как тип `HttpUrl` из модуля Pydantic вместо типа `str`:
diff --git a/docs/ru/docs/tutorial/body.md b/docs/ru/docs/tutorial/body.md
index c03d40c3f..96f80af06 100644
--- a/docs/ru/docs/tutorial/body.md
+++ b/docs/ru/docs/tutorial/body.md
@@ -6,7 +6,7 @@
Ваш API почти всегда отправляет тело **ответа**. Но клиентам не обязательно всегда отправлять тело **запроса**.
-Чтобы объявить тело **запроса**, необходимо использовать модели
Pydantic, со всей их мощью и преимуществами.
+Чтобы объявить тело **запроса**, необходимо использовать модели
Pydantic, со всей их мощью и преимуществами.
!!! info "Информация"
Чтобы отправить данные, необходимо использовать один из методов: `POST` (обычно), `PUT`, `DELETE` или `PATCH`.
diff --git a/docs/ru/docs/tutorial/dependencies/index.md b/docs/ru/docs/tutorial/dependencies/index.md
new file mode 100644
index 000000000..ad6e835e5
--- /dev/null
+++ b/docs/ru/docs/tutorial/dependencies/index.md
@@ -0,0 +1,350 @@
+# Зависимости
+
+**FastAPI** имеет очень мощную и интуитивную систему **
Dependency Injection**.
+
+Она проектировалась таким образом, чтобы быть простой в использовании и облегчить любому разработчику интеграцию других компонентов с **FastAPI**.
+
+## Что такое "Dependency Injection" (инъекция зависимости)
+
+**"Dependency Injection"** в программировании означает, что у вашего кода (в данном случае, вашей *функции обработки пути*) есть способы объявить вещи, которые запрашиваются для работы и использования: "зависимости".
+
+И потом эта система (в нашем случае **FastAPI**) организует всё, что требуется, чтобы обеспечить ваш код этой зависимостью (сделать "инъекцию" зависимости).
+
+Это очень полезно, когда вам нужно:
+
+* Обеспечить общую логику (один и тот же алгоритм снова и снова).
+* Общее соединение с базой данных.
+* Обеспечение безопасности, аутентификации, запроса роли и т.п.
+* И многое другое.
+
+Всё это минимизирует повторение кода.
+
+## Первые шаги
+
+Давайте рассмотрим очень простой пример. Он настолько простой, что на данный момент почти бесполезный.
+
+Но таким способом мы можем сфокусироваться на том, как же всё таки работает система **Dependency Injection**.
+
+### Создание зависимости или "зависимого"
+Давайте для начала сфокусируемся на зависимостях.
+
+Это просто функция, которая может принимать все те же параметры, что и *функции обработки пути*:
+=== "Python 3.10+"
+
+ ```Python hl_lines="8-9"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="8-11"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.8+"
+
+ ```Python hl_lines="9-12"
+ {!> ../../../docs_src/dependencies/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip "Подсказка"
+ Настоятельно рекомендуем использовать `Annotated` версию насколько это возможно.
+
+ ```Python hl_lines="6-7"
+ {!> ../../../docs_src/dependencies/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.8+ non-Annotated"
+
+ !!! tip "Подсказка"
+
+ Настоятельно рекомендуем использовать `Annotated` версию насколько это возможно.
+
+ ```Python hl_lines="8-11"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
+**И всё.**
+
+**2 строки.**
+
+И теперь она той же формы и структуры, что и все ваши *функции обработки пути*.
+
+Вы можете думать об *функции обработки пути* как о функции без "декоратора" (без `@app.get("/some-path")`).
+
+И она может возвращать всё, что требуется.
+
+В этом случае, эта зависимость ожидает:
+
+* Необязательный query-параметр `q` с типом `str`
+* Необязательный query-параметр `skip` с типом `int`, и значением по умолчанию `0`
+* Необязательный query-параметр `limit` с типом `int`, и значением по умолчанию `100`
+
+И в конце она возвращает `dict`, содержащий эти значения.
+
+!!! Информация
+
+ **FastAPI** добавил поддержку для `Annotated` (и начал её рекомендовать) в версии 0.95.0.
+
+ Если у вас более старая версия, будут ошибки при попытке использовать `Annotated`.
+
+ Убедитесь, что вы [Обновили FastAPI версию](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} до, как минимум 0.95.1, перед тем как использовать `Annotated`.
+
+### Import `Depends`
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.8+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/dependencies/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip "Подсказка"
+ Настоятельно рекомендуем использовать `Annotated` версию насколько это возможно.
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/dependencies/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.8+ non-Annotated"
+
+ !!! tip "Подсказка"
+ Настоятельно рекомендуем использовать `Annotated` версию насколько это возможно.
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
+### Объявите зависимость в "зависимом"
+
+Точно так же, как вы использовали `Body`, `Query` и т.д. с вашей *функцией обработки пути* для параметров, используйте `Depends` с новым параметром:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="13 18"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="15 20"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.8+"
+
+ ```Python hl_lines="16 21"
+ {!> ../../../docs_src/dependencies/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip "Подсказка"
+ Настоятельно рекомендуем использовать `Annotated` версию насколько это возможно.
+
+ ```Python hl_lines="11 16"
+ {!> ../../../docs_src/dependencies/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.8+ non-Annotated"
+
+ !!! tip "Подсказка"
+ Настоятельно рекомендуем использовать `Annotated` версию насколько это возможно.
+
+ ```Python hl_lines="15 20"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
+`Depends` работает немного иначе. Вы передаёте в `Depends` одиночный параметр, который будет похож на функцию.
+
+Вы **не вызываете его** на месте (не добавляете скобочки в конце: 👎 *your_best_func()*👎), просто передаёте как параметр в `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** знает, что делать дальше.
+
+## Объединяем с `Annotated` зависимостями
+
+В приведенном выше примере есть небольшое **повторение кода**.
+
+Когда вам нужно использовать `common_parameters()` зависимость, вы должны написать весь параметр с аннотацией типов и `Depends()`:
+
+```Python
+commons: Annotated[dict, Depends(common_parameters)]
+```
+
+Но потому что мы используем `Annotated`, мы можем хранить `Annotated` значение в переменной и использовать его в нескольких местах:
+
+=== "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.8+"
+
+ ```Python hl_lines="15 19 24"
+ {!> ../../../docs_src/dependencies/tutorial001_02_an.py!}
+ ```
+
+!!! tip "Подсказка"
+ Это стандартный синтаксис python и называется "type alias", это не особенность **FastAPI**.
+
+ Но потому что **FastAPI** базируется на стандартах Python, включая `Annotated`, вы можете использовать этот трюк в вашем коде. 😎
+
+
+Зависимости продолжат работу как ожидалось, и **лучшая часть** в том, что **информация о типе будет сохранена**. Это означает, что ваш редактор кода будет корректно обрабатывать **автодополнения**, **встроенные ошибки** и так далее. То же самое относится и к инструментам, таким как `mypy`.
+
+Это очень полезно, когда вы интегрируете это в **большую кодовую базу**, используя **одинаковые зависимости** снова и снова во **многих** ***операциях пути***.
+
+## Использовать `async` или не `async`
+
+Для зависимостей, вызванных **FastAPI** (то же самое, что и ваши *функции обработки пути*), те же правила, что приняты для определения ваших функций.
+
+Вы можете использовать `async def` или обычное `def`.
+
+Вы также можете объявить зависимости с `async def` внутри обычной `def` *функции обработки пути*, или `def` зависимости внутри `async def` *функции обработки пути*, и так далее.
+
+Это всё не важно. **FastAPI** знает, что нужно сделать. 😎
+
+!!! note "Информация"
+ Если вам эта тема не знакома, прочтите [Async: *"In a hurry?"*](../../async.md){.internal-link target=_blank} раздел о `async` и `await` в документации.
+
+## Интеграция с OpenAPI
+
+Все заявления о запросах, валидаторы, требования ваших зависимостей (и подзависимостей) будут интегрированы в соответствующую OpenAPI-схему.
+
+В интерактивной документации будет вся информация по этим зависимостям тоже:
+
+

+
+## Простое использование
+
+Если вы посмотрите на фото, *функция обработки пути* объявляется каждый раз, когда вычисляется путь, и тогда **FastAPI** позаботится о вызове функции с корректными параметрами, извлекая информацию из запроса.
+
+На самом деле, все (или большинство) веб-фреймворков работают по схожему сценарию.
+
+Вы никогда не вызываете эти функции на месте. Их вызовет ваш фреймворк (в нашем случае, **FastAPI**).
+
+С системой Dependency Injection, вы можете сообщить **FastAPI**, что ваша *функция обработки пути* "зависит" от чего-то ещё, что должно быть извлечено перед вашей *функцией обработки пути*, и **FastAPI** позаботится об извлечении и инъекции результата.
+
+Другие распространённые термины для описания схожей идеи "dependency injection" являются:
+
+- ресурсность
+- доставка
+- сервисность
+- инъекция
+- компонентность
+
+## **FastAPI** подключаемые модули
+
+Инъекции и модули могут быть построены с использованием системы **Dependency Injection**. Но на самом деле, **нет необходимости создавать новые модули**, просто используя зависимости, можно объявить бесконечное количество интеграций и взаимодействий, которые доступны вашей *функции обработки пути*.
+
+И зависимости могут быть созданы очень простым и интуитивным способом, что позволяет вам просто импортировать нужные пакеты Python и интегрировать их в API функции за пару строк.
+
+Вы увидите примеры этого в следующих главах о реляционных и NoSQL базах данных, безопасности и т.д.
+
+## Совместимость с **FastAPI**
+
+Простота Dependency Injection делает **FastAPI** совместимым с:
+
+- всеми реляционными базами данных
+- NoSQL базами данных
+- внешними пакетами
+- внешними API
+- системами авторизации, аутентификации
+- системами мониторинга использования API
+- системами ввода данных ответов
+- и так далее.
+
+## Просто и сильно
+
+Хотя иерархическая система Dependency Injection очень проста для описания и использования, она по-прежнему очень мощная.
+
+Вы можете описывать зависимости в очередь, и они уже будут вызываться друг за другом.
+
+Когда иерархическое дерево построено, система **Dependency Injection** берет на себя решение всех зависимостей для вас (и их подзависимостей) и обеспечивает (инъектирует) результат на каждом шаге.
+
+Например, у вас есть 4 API-эндпоинта (*операции пути*):
+
+- `/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
+```
+
+## Интегрировано с **OpenAPI**
+
+Все эти зависимости, объявляя свои требования, также добавляют параметры, проверки и т.д. к вашим операциям *path*.
+
+**FastAPI** позаботится о добавлении всего этого в схему открытого API, чтобы это отображалось в системах интерактивной документации.
diff --git a/docs/ru/docs/tutorial/extra-data-types.md b/docs/ru/docs/tutorial/extra-data-types.md
index 0f613a6b2..d4727e2d4 100644
--- a/docs/ru/docs/tutorial/extra-data-types.md
+++ b/docs/ru/docs/tutorial/extra-data-types.md
@@ -36,7 +36,7 @@
* `datetime.timedelta`:
* Встроенный в Python `datetime.timedelta`.
* В запросах и ответах будет представлен в виде общего количества секунд типа `float`.
- * Pydantic также позволяет представить его как "Кодировку разницы во времени ISO 8601",
см. документацию для получения дополнительной информации.
+ * Pydantic также позволяет представить его как "Кодировку разницы во времени ISO 8601",
см. документацию для получения дополнительной информации.
* `frozenset`:
* В запросах и ответах обрабатывается так же, как и `set`:
* В запросах будет прочитан список, исключены дубликаты и преобразован в `set`.
@@ -49,7 +49,7 @@
* `Decimal`:
* Встроенный в Python `Decimal`.
* В запросах и ответах обрабатывается так же, как и `float`.
-* Вы можете проверить все допустимые типы данных pydantic здесь:
Типы данных Pydantic.
+* Вы можете проверить все допустимые типы данных pydantic здесь:
Типы данных Pydantic.
## Пример
diff --git a/docs/ru/docs/tutorial/extra-models.md b/docs/ru/docs/tutorial/extra-models.md
index 30176b4e3..78855313d 100644
--- a/docs/ru/docs/tutorial/extra-models.md
+++ b/docs/ru/docs/tutorial/extra-models.md
@@ -179,7 +179,7 @@ UserInDB(
Для этого используйте стандартные аннотации типов в Python
`typing.Union`:
!!! note "Примечание"
- При объявлении
`Union`, сначала указывайте наиболее детальные типы, затем менее детальные. В примере ниже более детальный `PlaneItem` стоит перед `CarItem` в `Union[PlaneItem, CarItem]`.
+ При объявлении
`Union`, сначала указывайте наиболее детальные типы, затем менее детальные. В примере ниже более детальный `PlaneItem` стоит перед `CarItem` в `Union[PlaneItem, CarItem]`.
=== "Python 3.10+"
diff --git a/docs/ru/docs/tutorial/handling-errors.md b/docs/ru/docs/tutorial/handling-errors.md
index f578cf198..40b6f9bc4 100644
--- a/docs/ru/docs/tutorial/handling-errors.md
+++ b/docs/ru/docs/tutorial/handling-errors.md
@@ -163,7 +163,7 @@ path -> item_id
!!! warning "Внимание"
Это технические детали, которые можно пропустить, если они не важны для вас сейчас.
-`RequestValidationError` является подклассом Pydantic
`ValidationError`.
+`RequestValidationError` является подклассом Pydantic
`ValidationError`.
**FastAPI** использует его для того, чтобы, если вы используете Pydantic-модель в `response_model`, и ваши данные содержат ошибку, вы увидели ошибку в журнале.
diff --git a/docs/ru/docs/tutorial/metadata.md b/docs/ru/docs/tutorial/metadata.md
index 331c96734..468e08917 100644
--- a/docs/ru/docs/tutorial/metadata.md
+++ b/docs/ru/docs/tutorial/metadata.md
@@ -65,7 +65,7 @@
```
!!! info "Дополнительная информация"
- Узнайте больше о тегах в [Конфигурации операции пути](../path-operation-configuration/#tags){.internal-link target=_blank}.
+ Узнайте больше о тегах в [Конфигурации операции пути](path-operation-configuration.md#tags){.internal-link target=_blank}.
### Проверьте документацию
diff --git a/docs/ru/docs/tutorial/path-params.md b/docs/ru/docs/tutorial/path-params.md
index 55b498ef0..1241e0919 100644
--- a/docs/ru/docs/tutorial/path-params.md
+++ b/docs/ru/docs/tutorial/path-params.md
@@ -93,7 +93,7 @@
## Pydantic
-Вся проверка данных выполняется под капотом с помощью
Pydantic. Поэтому вы можете быть уверены в качестве обработки данных.
+Вся проверка данных выполняется под капотом с помощью
Pydantic. Поэтому вы можете быть уверены в качестве обработки данных.
Вы можете использовать в аннотациях как простые типы данных, вроде `str`, `float`, `bool`, так и более сложные типы.
diff --git a/docs/ru/docs/tutorial/query-params-str-validations.md b/docs/ru/docs/tutorial/query-params-str-validations.md
index cc826b871..108aefefc 100644
--- a/docs/ru/docs/tutorial/query-params-str-validations.md
+++ b/docs/ru/docs/tutorial/query-params-str-validations.md
@@ -479,7 +479,7 @@ q: Union[str, None] = None
```
!!! tip "Подсказка"
- Pydantic, мощь которого используется в FastAPI для валидации и сериализации, имеет специальное поведение для `Optional` или `Union[Something, None]` без значения по умолчанию. Вы можете узнать об этом больше в документации Pydantic, раздел
Обязательные Опциональные поля.
+ Pydantic, мощь которого используется в FastAPI для валидации и сериализации, имеет специальное поведение для `Optional` или `Union[Something, None]` без значения по умолчанию. Вы можете узнать об этом больше в документации Pydantic, раздел
Обязательные Опциональные поля.
### Использование Pydantic's `Required` вместо Ellipsis (`...`)
diff --git a/docs/ru/docs/tutorial/request-files.md b/docs/ru/docs/tutorial/request-files.md
index 00f8c8377..79b3bd067 100644
--- a/docs/ru/docs/tutorial/request-files.md
+++ b/docs/ru/docs/tutorial/request-files.md
@@ -3,7 +3,7 @@
Используя класс `File`, мы можем позволить клиентам загружать файлы.
!!! info "Дополнительная информация"
- Чтобы получать загруженные файлы, сначала установите
`python-multipart`.
+ Чтобы получать загруженные файлы, сначала установите
`python-multipart`.
Например: `pip install python-multipart`.
diff --git a/docs/ru/docs/tutorial/request-forms-and-files.md b/docs/ru/docs/tutorial/request-forms-and-files.md
index 3f587c38a..a08232ca7 100644
--- a/docs/ru/docs/tutorial/request-forms-and-files.md
+++ b/docs/ru/docs/tutorial/request-forms-and-files.md
@@ -3,7 +3,7 @@
Вы можете определять файлы и поля формы одновременно, используя `File` и `Form`.
!!! info "Дополнительная информация"
- Чтобы получать загруженные файлы и/или данные форм, сначала установите
`python-multipart`.
+ Чтобы получать загруженные файлы и/или данные форм, сначала установите
`python-multipart`.
Например: `pip install python-multipart`.
diff --git a/docs/ru/docs/tutorial/request-forms.md b/docs/ru/docs/tutorial/request-forms.md
index 0fc9e4eda..fa2bcb7cb 100644
--- a/docs/ru/docs/tutorial/request-forms.md
+++ b/docs/ru/docs/tutorial/request-forms.md
@@ -3,7 +3,7 @@
Когда вам нужно получить поля формы вместо JSON, вы можете использовать `Form`.
!!! info "Дополнительная информация"
- Чтобы использовать формы, сначала установите
`python-multipart`.
+ Чтобы использовать формы, сначала установите
`python-multipart`.
Например, выполните команду `pip install python-multipart`.
diff --git a/docs/ru/docs/tutorial/response-model.md b/docs/ru/docs/tutorial/response-model.md
index 38b45e2a5..9b9b60dd5 100644
--- a/docs/ru/docs/tutorial/response-model.md
+++ b/docs/ru/docs/tutorial/response-model.md
@@ -377,7 +377,7 @@ FastAPI совместно с Pydantic выполнит некоторую ма
```
!!! info "Информация"
- "Под капотом" FastAPI использует метод `.dict()` у объектов моделей Pydantic
с параметром `exclude_unset`, чтобы достичь такого эффекта.
+ "Под капотом" FastAPI использует метод `.dict()` у объектов моделей Pydantic
с параметром `exclude_unset`, чтобы достичь такого эффекта.
!!! info "Информация"
Вы также можете использовать:
@@ -385,7 +385,7 @@ FastAPI совместно с Pydantic выполнит некоторую ма
* `response_model_exclude_defaults=True`
* `response_model_exclude_none=True`
- как описано в
документации Pydantic для параметров `exclude_defaults` и `exclude_none`.
+ как описано в
документации Pydantic для параметров `exclude_defaults` и `exclude_none`.
#### Если значение поля отличается от значения по-умолчанию
diff --git a/docs/ru/docs/tutorial/schema-extra-example.md b/docs/ru/docs/tutorial/schema-extra-example.md
index a13ab5935..e1011805a 100644
--- a/docs/ru/docs/tutorial/schema-extra-example.md
+++ b/docs/ru/docs/tutorial/schema-extra-example.md
@@ -6,7 +6,7 @@
## Pydantic `schema_extra`
-Вы можете объявить ключ `example` для модели Pydantic, используя класс `Config` и переменную `schema_extra`, как описано в
Pydantic документации: Настройка схемы:
+Вы можете объявить ключ `example` для модели Pydantic, используя класс `Config` и переменную `schema_extra`, как описано в
Pydantic документации: Настройка схемы:
=== "Python 3.10+"
diff --git a/docs/ru/docs/tutorial/security/first-steps.md b/docs/ru/docs/tutorial/security/first-steps.md
index b70a60a38..fdeccc01a 100644
--- a/docs/ru/docs/tutorial/security/first-steps.md
+++ b/docs/ru/docs/tutorial/security/first-steps.md
@@ -45,7 +45,7 @@
## Запуск
!!! info "Дополнительная информация"
- Вначале, установите библиотеку
`python-multipart`.
+ Вначале, установите библиотеку
`python-multipart`.
А именно: `pip install python-multipart`.
diff --git a/docs/tr/docs/alternatives.md b/docs/tr/docs/alternatives.md
index 9c69503c9..462d8b304 100644
--- a/docs/tr/docs/alternatives.md
+++ b/docs/tr/docs/alternatives.md
@@ -336,7 +336,7 @@ Artık APIStar, OpenAPI özelliklerini doğrulamak için bir dizi araç sunan bi
## **FastAPI** Tarafından Kullanılanlar
-###
Pydantic
+###
Pydantic
Pydantic Python tip belirteçlerine dayanan; veri doğrulama, veri dönüştürme ve dökümantasyon tanımlamak (JSON Şema kullanarak) için bir kütüphanedir.
diff --git a/docs/tr/docs/async.md b/docs/tr/docs/async.md
index 2be594343..aab939189 100644
--- a/docs/tr/docs/async.md
+++ b/docs/tr/docs/async.md
@@ -376,7 +376,7 @@ FastAPI'ye (Starlette aracılığıyla) güç veren ve bu kadar etkileyici bir p
Yukarıda açıklanan şekilde çalışmayan başka bir asenkron framework'den geliyorsanız ve küçük bir performans kazancı (yaklaşık 100 nanosaniye) için "def" ile *path fonksiyonu* tanımlamaya alışkınsanız, **FastAPI**'de tam tersi olacağını unutmayın. Bu durumlarda, *path fonksiyonu*
G/Ç engelleyen durum oluşturmadıkça "async def" kullanmak daha iyidir.
-Yine de, her iki durumda da, **FastAPI**'nin önceki frameworkden [hala daha hızlı](/#performance){.internal-link target=_blank} (veya en azından karşılaştırılabilir) olma olasılığı vardır.
+Yine de, her iki durumda da, **FastAPI**'nin önceki frameworkden [hala daha hızlı](index.md#performance){.internal-link target=_blank} (veya en azından karşılaştırılabilir) olma olasılığı vardır.
### Bagımlılıklar
diff --git a/docs/tr/docs/fastapi-people.md b/docs/tr/docs/fastapi-people.md
index 3e459036a..6dd4ec061 100644
--- a/docs/tr/docs/fastapi-people.md
+++ b/docs/tr/docs/fastapi-people.md
@@ -1,10 +1,15 @@
+---
+hide:
+ - navigation
+---
+
# FastAPI Topluluğu
FastAPI, her kökenden insanı ağırlayan harika bir topluluğa sahip.
## Yazan - Geliştiren
-Hey! 👋
+Merhaba! 👋
İşte bu benim:
@@ -12,38 +17,37 @@ Hey! 👋
{% for user in people.maintainers %}
-
+
{% endfor %}
{% endif %}
-Ben **FastAPI** 'nin yazarı ve geliştiricisiyim. Bununla ilgili daha fazla bilgiyi şurada okuyabilirsiniz:
- [FastAPI yardım - yardım al - Yazar ile iletişime geç](help-fastapi.md#connect-with-the-author){.internal-link target=_blank}.
+Ben **FastAPI**'ın geliştiricisiyim. Bununla ilgili daha fazla bilgiyi şurada okuyabilirsiniz: [FastAPI yardım - yardım al - benimle iletişime geç](help-fastapi.md#connect-with-the-author){.internal-link target=_blank}.
-... Burada size harika FastAPI topluluğunu göstermek istiyorum.
+...burada size harika FastAPI topluluğunu göstermek istiyorum.
---
-**FastAPI** topluluğundan destek alıyor. Ve katkıda bulunanları vurgulamak istiyorum.
+**FastAPI**, topluluğundan çok destek alıyor. Ben de onların katkılarını vurgulamak istiyorum.
-İşte o mükemmel insanlar:
+Bu insanlar:
-* [GitHubdaki sorunları (issues) çözmelerinde diğerlerine yardım et](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank}.
-* [Pull Requests oluşturun](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}.
-* Pull Requests 'leri gözden geçirin, [özelliklede çevirileri](contributing.md#translations){.internal-link target=_blank}.
+* [GitHubdaki soruları cevaplayarak diğerlerine yardım ediyor](help-fastapi.md#help-others-with-questions-in-github){.internal-link target=_blank}.
+* [Pull Request'ler oluşturuyor](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}.
+* Pull Request'leri gözden geçiriyorlar, [özellikle çeviriler için bu çok önemli](contributing.md#translations){.internal-link target=_blank}.
-Onlara bir alkış. 👏 🙇
+Onları bir alkışlayalım. 👏 🙇
-## Geçen ayın en aktif kullanıcıları
+## Geçen Ayın En Aktif Kullanıcıları
-Bunlar geçen ay boyunca [GitHub' da başkalarına sorunlarında (issues) en çok yardımcı olan ](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank} kullanıcılar ☕
+Geçtiğimiz ay boyunca [GitHub'da diğerlerine en çok yardımcı olan](help-fastapi.md#help-others-with-questions-in-github){.internal-link target=_blank} kullanıcılar. ☕
{% if people %}
-{% for user in people.last_month_active %}
+{% for user in people.last_month_experts[:10] %}
-
+
{% endfor %}
@@ -53,57 +57,57 @@ Bunlar geçen ay boyunca [GitHub' da başkalarına sorunlarında (issues) en ço
İşte **FastAPI Uzmanları**. 🤓
-Bunlar *tüm zamanlar boyunca* [GitHub' da başkalarına sorunlarında (issues) en çok yardımcı olan](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank} kullanıcılar.
+Uzmanlarımız ise *tüm zamanlar boyunca* [GitHub'da insanların sorularına en çok yardımcı olan](help-fastapi.md#help-others-with-questions-in-github){.internal-link target=_blank} insanlar.
-Başkalarına yardım ederek uzman olduklarını kanıtladılar. ✨
+Bir çok kullanıcıya yardım ederek uzman olduklarını kanıtladılar! ✨
{% if people %}
-{% for user in people.experts %}
+{% for user in people.experts[:50] %}
-
+
{% endfor %}
{% endif %}
-## En fazla katkıda bulunanlar
+## En Fazla Katkıda Bulunanlar
-işte **En fazla katkıda bulunanlar**. 👷
+Şimdi ise sıra **en fazla katkıda bulunanlar**da. 👷
-Bu kullanıcılar en çok [Pull Requests oluşturan](help-fastapi.md#create-a-pull-request){.internal-link target=_blank} ve onu kaynak koduna *birleştirenler*.
+Bu kullanıcılar en fazla [kaynak koduyla birleştirilen Pull Request'lere](help-fastapi.md#create-a-pull-request){.internal-link target=_blank} sahip!
-Kaynak koduna, belgelere, çevirilere vb. katkıda bulundular. 📦
+Kaynak koduna, dökümantasyona, çevirilere ve bir sürü şeye katkıda bulundular. 📦
{% if people %}
-{% for user in people.top_contributors %}
+{% for user in people.top_contributors[:50] %}
-
+
{% endfor %}
{% endif %}
-Çok fazla katkıda bulunan var (binden fazla), hepsini şurda görebilirsin:
FastAPI GitHub Katkıda Bulunanlar. 👷
+Bunlar dışında katkıda bulunan, yüzden fazla, bir sürü insan var. Hepsini
FastAPI GitHub Katkıda Bulunanlar sayfasında görebilirsin. 👷
-## En fazla inceleme yapanlar
+## En Fazla Değerlendirme Yapanlar
-İşte **En fazla inceleme yapanlar**. 🕵️
+İşte **en çok değerlendirme yapanlar**. 🕵️
-### Çeviri için İncelemeler
+### Çeviri Değerlendirmeleri
-Yalnızca birkaç dil konuşabiliyorum (ve çok da iyi değilim 😅). Bu yüzden döküman çevirilerini [**onaylama yetkisi**](contributing.md#translations){.internal-link target=_blank} siz inceleyenlere aittir. Sizler olmadan diğer birkaç dilde dokümantasyon olmazdı.
+Yalnızca birkaç dil konuşabiliyorum (ve çok da iyi değilim 😅). Bu yüzden değerlendirme yapanların da döküman çevirilerini [**onaylama yetkisi**](contributing.md#translations){.internal-link target=_blank} var. Onlar olmasaydı çeşitli dillerde dökümantasyon da olmazdı.
---
-**En fazla inceleme yapanlar** 🕵️ kodun, belgelerin ve özellikle **çevirilerin** kalitesini sağlamak için diğerlerinden daha fazla pull requests incelemiştir.
+**En fazla değerlendirme yapanlar** 🕵️ kodun, dökümantasyonun ve özellikle **çevirilerin** Pull Request'lerini inceleyerek kalitesinden emin oldular.
{% if people %}
-{% for user in people.top_reviewers %}
+{% for user in people.top_translations_reviewers[:50] %}
-
+
{% endfor %}
@@ -113,66 +117,67 @@ Yalnızca birkaç dil konuşabiliyorum (ve çok da iyi değilim 😅). Bu yüzde
işte **Sponsorlarımız**. 😎
-**FastAPI** ve diğer projelerde çalışmamı destekliyorlar, özellikle de
GitHub Sponsorları.
+Çoğunlukla
GitHub Sponsorları aracılığıyla olmak üzere, **FastAPI** ve diğer projelerdeki çalışmalarımı destekliyorlar.
+
+{% if sponsors %}
+
+{% if sponsors.gold %}
### Altın Sponsorlar
-{% if sponsors %}
{% for sponsor in sponsors.gold -%}

{% endfor %}
{% endif %}
+{% if sponsors.silver %}
+
### Gümüş Sponsorlar
-{% if sponsors %}
{% for sponsor in sponsors.silver -%}

{% endfor %}
{% endif %}
+{% if sponsors.bronze %}
+
### Bronz Sponsorlar
-{% if sponsors %}
{% for sponsor in sponsors.bronze -%}

{% endfor %}
{% endif %}
+{% endif %}
+
### Bireysel Sponsorlar
-{% if people %}
-{% if people.sponsors_50 %}
+{% if github_sponsors %}
+{% for group in github_sponsors.sponsors %}
-{% for user in people.sponsors_50 %}
-
-{% endfor %}
+{% for user in group %}
+{% if user.login not in sponsors_badge.logins %}
-
+
{% endif %}
-{% endif %}
-
-{% if people %}
-
-{% for user in people.sponsors %}
-
-
{% endfor %}
+
+{% endfor %}
{% endif %}
-## Veriler hakkında - Teknik detaylar
+## Veriler - Teknik detaylar
Bu sayfanın temel amacı, topluluğun başkalarına yardım etme çabasını vurgulamaktır.
-Özellikle normalde daha az görünür olan ve çoğu durumda daha zahmetli olan, diğerlerine sorunlar konusunda yardımcı olmak ve pull requests'leri gözden geçirmek gibi çabalar dahil.
+Özellikle normalde daha az görünür olan ve çoğu durumda daha zahmetli olan, diğerlerine sorularında yardımcı olmak, çevirileri ve Pull Request'leri gözden geçirmek gibi çabalar dahil.
-Veriler ayda bir hesaplanır, işte kaynak kodu okuyabilirsin :
source code here.
+Veriler ayda bir hesaplanır,
kaynak kodu buradan okuyabilirsin.
-Burada sponsorların katkılarını da tekrardan vurgulamak isterim.
+Burada sponsorların katkılarını da vurguluyorum.
-Ayrıca algoritmayı, bölümleri, eşikleri vb. güncelleme hakkımı da saklı tutarım (her ihtimale karşı 🤷).
+Ayrıca algoritmayı, bölümleri, eşikleri vb. güncelleme hakkımı da saklı tutuyorum (her ihtimale karşı 🤷).
diff --git a/docs/tr/docs/features.md b/docs/tr/docs/features.md
index 8b143ffe7..1cda8c7fb 100644
--- a/docs/tr/docs/features.md
+++ b/docs/tr/docs/features.md
@@ -182,7 +182,7 @@ Bütün entegrasyonlar kullanımı kolay olmak üzere (zorunluluklar ile beraber
## Pydantic özellikleri
-**FastAPI** ile
Pydantic tamamiyle uyumlu ve üzerine kurulu. Yani FastAPI üzerine ekleme yapacağınız herhangi bir Pydantic kodu da çalışacaktır.
+**FastAPI** ile
Pydantic tamamiyle uyumlu ve üzerine kurulu. Yani FastAPI üzerine ekleme yapacağınız herhangi bir Pydantic kodu da çalışacaktır.
Bunlara Pydantic üzerine kurulu
ORM databaseler ve ,
ODM kütüphaneler de dahil olmak üzere.
@@ -197,8 +197,6 @@ Aynı şekilde, databaseden gelen objeyi de **direkt olarak isteğe** de tamamiy
* Eğer Python typelarını nasıl kullanacağını biliyorsan Pydantic kullanmayı da biliyorsundur.
* Kullandığın geliştirme araçları ile iyi çalışır **
IDE/
linter/brain**:
* Pydantic'in veri yapıları aslında sadece senin tanımladığın classlar; Bu yüzden doğrulanmış dataların ile otomatik tamamlama, linting ve mypy'ı kullanarak sorunsuz bir şekilde çalışabilirsin
-* **Hızlı**:
- *
Benchmarklarda, Pydantic'in diğer bütün test edilmiş bütün kütüphanelerden daha hızlı.
* **En kompleks** yapıları bile doğrula:
* Hiyerarşik Pydantic modellerinin kullanımı ile beraber, Python `typing`’s `List` and `Dict`, vs gibi şeyleri doğrula.
* Doğrulayıcılar en kompleks data şemalarının bile temiz ve kolay bir şekilde tanımlanmasına izin veriyor, ve hepsi JSON şeması olarak dokümante ediliyor
diff --git a/docs/tr/docs/history-design-future.md b/docs/tr/docs/history-design-future.md
index 950fcf37d..1dd0e637f 100644
--- a/docs/tr/docs/history-design-future.md
+++ b/docs/tr/docs/history-design-future.md
@@ -54,7 +54,7 @@ Hepsi, tüm geliştiriciler için en iyi geliştirme deneyimini sağlayacak şek
## Gereksinimler
-Çeşitli alternatifleri test ettikten sonra, avantajlarından dolayı
**Pydantic**'i kullanmaya karar verdim.
+Çeşitli alternatifleri test ettikten sonra, avantajlarından dolayı
**Pydantic**'i kullanmaya karar verdim.
Sonra, JSON Schema ile tamamen uyumlu olmasını sağlamak, kısıtlama bildirimlerini tanımlamanın farklı yollarını desteklemek ve birkaç editördeki testlere dayanarak editör desteğini (tip kontrolleri, otomatik tamamlama) geliştirmek için katkıda bulundum.
diff --git a/docs/tr/docs/index.md b/docs/tr/docs/index.md
index ac8830880..afbb27f7d 100644
--- a/docs/tr/docs/index.md
+++ b/docs/tr/docs/index.md
@@ -120,7 +120,7 @@ Python 3.8+
FastAPI iki devin omuzları üstünde duruyor:
* Web tarafı için
Starlette.
-* Data tarafı için
Pydantic.
+* Data tarafı için
Pydantic.
## Kurulum
@@ -453,7 +453,7 @@ Starlette tarafında kullanılan:
*
httpx
- Eğer `TestClient` yapısını kullanacaksanız gereklidir.
*
jinja2
- Eğer varsayılan template konfigürasyonunu kullanacaksanız gereklidir.
-*
python-multipart
- Eğer `request.form()` ile form
dönüşümü desteğini kullanacaksanız gereklidir.
+*
python-multipart
- Eğer `request.form()` ile form
dönüşümü desteğini kullanacaksanız gereklidir.
*
itsdangerous
- `SessionMiddleware` desteği için gerekli.
*
pyyaml
- `SchemaGenerator` desteği için gerekli (Muhtemelen FastAPI kullanırken ihtiyacınız olmaz).
*
ujson
- `UJSONResponse` kullanacaksanız gerekli.
diff --git a/docs/tr/docs/python-types.md b/docs/tr/docs/python-types.md
index 3b9ab9050..a0d32c86e 100644
--- a/docs/tr/docs/python-types.md
+++ b/docs/tr/docs/python-types.md
@@ -265,7 +265,7 @@ Ve yine bütün editör desteğini alırsınız:
## Pydantic modelleri
-
Pydantic veri doğrulaması yapmak için bir Python kütüphanesidir.
+
Pydantic veri doğrulaması yapmak için bir Python kütüphanesidir.
Verilerin "biçimini" niteliklere sahip sınıflar olarak düzenlersiniz.
@@ -282,7 +282,7 @@ Resmi Pydantic dokümanlarından alınmıştır:
```
!!! info
- Daha fazla şey öğrenmek için
Pydantic'i takip edin.
+ Daha fazla şey öğrenmek için
Pydantic'i takip edin.
**FastAPI** tamamen Pydantic'e dayanmaktadır.
diff --git a/docs/tr/docs/tutorial/first-steps.md b/docs/tr/docs/tutorial/first-steps.md
new file mode 100644
index 000000000..e66f73034
--- /dev/null
+++ b/docs/tr/docs/tutorial/first-steps.md
@@ -0,0 +1,333 @@
+# İlk Adımlar
+
+En sade FastAPI dosyası şu şekilde görünür:
+
+```Python
+{!../../../docs_src/first_steps/tutorial001.py!}
+```
+
+Yukarıdaki içeriği bir `main.py` dosyasına kopyalayalım.
+
+Uygulamayı çalıştıralım:
+
+
+
+```console
+$ uvicorn main:app --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [28720]
+INFO: Started server process [28722]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+!!! note "Not"
+ `uvicorn main:app` komutunu şu şekilde açıklayabiliriz:
+
+ * `main`: dosya olan `main.py` (yani Python "modülü").
+ * `app`: ise `main.py` dosyasının içerisinde `app = FastAPI()` satırında oluşturduğumuz `FastAPI` nesnesi.
+ * `--reload`: kod değişikliklerinin ardından sunucuyu otomatik olarak yeniden başlatır. Bu parameteyi sadece geliştirme aşamasında kullanmalıyız.
+
+Çıktı olarak şöyle bir satır ile karşılaşacaksınız:
+
+```hl_lines="4"
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+Bu satır, yerel makinenizde uygulamanızın çalıştığı bağlantıyı gösterir.
+
+### Kontrol Edelim
+
+Tarayıcınızı açıp
http://127.0.0.1:8000 bağlantısına gidin.
+
+Şu şekilde bir JSON yanıtı ile karşılaşacağız:
+
+```JSON
+{"message": "Hello World"}
+```
+
+### Etkileşimli API Dokümantasyonu
+
+Şimdi
http://127.0.0.1:8000/docs bağlantısını açalım.
+
+
Swagger UI tarafından sağlanan otomatik etkileşimli bir API dokümantasyonu göreceğiz:
+
+
+
+### Alternatif API Dokümantasyonu
+
+Şimdi
http://127.0.0.1:8000/redoc bağlantısını açalım.
+
+
ReDoc tarafından sağlanan otomatik dokümantasyonu göreceğiz:
+
+
+
+### OpenAPI
+
+**FastAPI**, **OpenAPI** standardını kullanarak tüm API'ınızın tamamını tanımlayan bir "şema" oluşturur.
+
+#### "Şema"
+
+"Şema", bir şeyin tanımı veya açıklamasıdır. Geliştirilen koddan ziyade soyut bir açıklamadır.
+
+#### API "Şeması"
+
+Bu durumda,
OpenAPI, API şemasını nasıl tanımlayacağınızı belirten bir şartnamedir.
+
+Bu şema tanımı, API yollarınızla birlikte yollarınızın aldığı olası parametreler gibi tanımlamaları içerir.
+
+#### Veri "Şeması"
+
+"Şema" terimi, JSON içeriği gibi bazı verilerin şeklini de ifade edebilir.
+
+Bu durumda, JSON özellikleri ve sahip oldukları veri türleri gibi anlamlarına gelir.
+
+#### OpenAPI ve JSON Şema
+
+OpenAPI, API'niz için bir API şeması tanımlar. Ve bu şema, JSON veri şemaları standardı olan **JSON Şema** kullanılarak API'niz tarafından gönderilen ve alınan verilerin tanımlarını (veya "şemalarını") içerir.
+
+#### `openapi.json` Dosyasına Göz At
+
+Ham OpenAPI şemasının nasıl göründüğünü merak ediyorsanız, FastAPI otomatik olarak tüm API'ınızın tanımlamalarını içeren bir JSON (şeması) oluşturur.
+
+Bu şemayı direkt olarak
http://127.0.0.1:8000/openapi.json bağlantısından görüntüleyebilirsiniz.
+
+Aşağıdaki gibi başlayan bir JSON ile karşılaşacaksınız:
+
+```JSON
+{
+ "openapi": "3.1.0",
+ "info": {
+ "title": "FastAPI",
+ "version": "0.1.0"
+ },
+ "paths": {
+ "/items/": {
+ "get": {
+ "responses": {
+ "200": {
+ "description": "Successful Response",
+ "content": {
+ "application/json": {
+
+
+
+...
+```
+
+#### OpenAPI Ne İşe Yarar?
+
+OpenAPI şeması, FastAPI projesinde bulunan iki etkileşimli dokümantasyon sistemine güç veren şeydir.
+
+OpenAPI'ya dayalı düzinelerce alternatif etkileşimli dokümantasyon aracı mevcuttur. **FastAPI** ile oluşturulmuş uygulamanıza bu alternatiflerden herhangi birini kolayca ekleyebilirsiniz.
+
+Ayrıca, API'ınızla iletişim kuracak önyüz, mobil veya IoT uygulamaları gibi istemciler için otomatik olarak kod oluşturabilirsiniz.
+
+## Adım Adım Özetleyelim
+
+### Adım 1: `FastAPI`yı Projemize Dahil Edelim
+
+```Python hl_lines="1"
+{!../../../docs_src/first_steps/tutorial001.py!}
+```
+
+`FastAPI`, API'niz için tüm işlevselliği sağlayan bir Python sınıfıdır.
+
+!!! note "Teknik Detaylar"
+ `FastAPI` doğrudan `Starlette`'i miras alan bir sınıftır.
+
+
Starlette'in tüm işlevselliğini `FastAPI` ile de kullanabilirsiniz.
+
+### Adım 2: Bir `FastAPI` "Örneği" Oluşturalım
+
+```Python hl_lines="3"
+{!../../../docs_src/first_steps/tutorial001.py!}
+```
+
+Burada `app` değişkeni `FastAPI` sınıfının bir örneği olacaktır.
+
+Bu, tüm API'yı oluşturmak için ana etkileşim noktası olacaktır.
+
+Bu `app` değişkeni, `uvicorn` komutunda atıfta bulunulan değişkenin ta kendisidir.
+
+
+
+```console
+$ uvicorn main:app --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+
+
+Uygulamanızı aşağıdaki gibi oluşturursanız:
+
+```Python hl_lines="3"
+{!../../../docs_src/first_steps/tutorial002.py!}
+```
+
+Ve bunu `main.py` dosyasına yerleştirirseniz eğer `uvicorn` komutunu şu şekilde çalıştırabilirsiniz:
+
+
+
+```console
+$ uvicorn main:my_awesome_api --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+
+
+### Adım 3: Bir *Yol Operasyonu* Oluşturalım
+
+####
Yol
+
+Burada "yol" bağlantıda bulunan ilk `/` ile başlayan ve sonrasında gelen kısmı ifade eder.
+
+Yani, şu şekilde bir bağlantıda:
+
+```
+https://example.com/items/foo
+```
+
+... yol şöyle olur:
+
+```
+/items/foo
+```
+
+!!! info "Bilgi"
+ "Yol" genellikle "
endpoint" veya "
route" olarak adlandırılır.
+
+Bir API oluştururken, "yol", "kaynaklar" ile "endişeleri" ayırmanın ana yöntemidir.
+
+#### Operasyonlar
+
+Burada "operasyon" HTTP "metodlarından" birini ifade eder.
+
+Bunlardan biri:
+
+* `POST`
+* `GET`
+* `PUT`
+* `DELETE`
+
+...veya daha az kullanılan diğerleri:
+
+* `OPTIONS`
+* `HEAD`
+* `PATCH`
+* `TRACE`
+
+HTTP protokolünde, bu "metodlardan" birini (veya daha fazlasını) kullanarak her bir yol ile iletişim kurabilirsiniz.
+
+---
+
+API oluştururkan, belirli bir amaca hizmet eden belirli HTTP metodlarını kullanırsınız.
+
+Normalde kullanılan:
+
+* `POST`: veri oluşturmak.
+* `GET`: veri okumak.
+* `PUT`: veriyi güncellemek.
+* `DELETE`: veriyi silmek.
+
+Bu nedenle, OpenAPI'da HTTP metodlarından her birine "operasyon" denir.
+
+Biz de onları "**operasyonlar**" olarak adlandıracağız.
+
+#### Bir *Yol Operasyonu Dekoratörü* Tanımlayalım
+
+```Python hl_lines="6"
+{!../../../docs_src/first_steps/tutorial001.py!}
+```
+
+`@app.get("/")` dekoratörü, **FastAPI**'a hemen altındaki fonksiyonun aşağıdaki durumlardan sorumlu olduğunu söyler:
+
+*
get
operasyonu ile
+* `/` yoluna gelen istekler
+
+!!! info "`@decorator` Bilgisi"
+ Python'da `@something` sözdizimi "
dekoratör" olarak adlandırılır.
+
+ Dekoratörler, dekoratif bir şapka gibi (sanırım terim buradan geliyor) fonksiyonların üzerlerine yerleştirilirler.
+
+ Bir "dekoratör" hemen altında bulunan fonksiyonu alır ve o fonksiyon ile bazı işlemler gerçekleştirir.
+
+ Bizim durumumuzda, kullandığımız dekoratör, **FastAPI**'a altındaki fonksiyonun `/` yoluna gelen `get` metodlu isteklerden sorumlu olduğunu söyler.
+
+ Bu bir **yol operasyonu dekoratörüdür**.
+
+Ayrıca diğer operasyonları da kullanabilirsiniz:
+
+* `@app.post()`
+* `@app.put()`
+* `@app.delete()`
+
+Daha az kullanılanları da kullanabilirsiniz:
+
+* `@app.options()`
+* `@app.head()`
+* `@app.patch()`
+* `@app.trace()`
+
+!!! tip "İpucu"
+ Her işlemi (HTTP metod) istediğiniz gibi kullanmakta özgürsünüz.
+
+ **FastAPI** herhangi bir özel amacı veya anlamı olması konusunda ısrarcı olmaz.
+
+ Buradaki bilgiler bir gereklilik değil, bir kılavuz olarak sunulmaktadır.
+
+ Mesela GraphQL kullanırkan genelde tüm işlemleri yalnızca `POST` operasyonunu kullanarak gerçekleştirirsiniz.
+
+### Adım 4: **Yol Operasyonu Fonksiyonunu** Tanımlayın
+
+Aşağıdaki, bizim **yol operasyonu fonksiyonumuzdur**:
+
+* **yol**: `/`
+* **operasyon**: `get`
+* **fonksiyon**: "dekoratör"ün (`@app.get("/")`'in) altındaki fonksiyondur.
+
+```Python hl_lines="7"
+{!../../../docs_src/first_steps/tutorial001.py!}
+```
+
+Bu bir Python fonksiyonudur.
+
+Bu fonksiyon bir `GET` işlemi kullanılarak "`/`" bağlantısına bir istek geldiğinde **FastAPI** tarafından çağrılır.
+
+Bu durumda bu fonksiyon bir `async` fonksiyondur.
+
+---
+
+Bu fonksiyonu `async def` yerine normal bir fonksiyon olarak da tanımlayabilirsiniz.
+
+```Python hl_lines="7"
+{!../../../docs_src/first_steps/tutorial003.py!}
+```
+
+!!! note "Not"
+ Eğer farkı bilmiyorsanız, [Async: *"Aceleniz mi var?"*](../async.md#in-a-hurry){.internal-link target=_blank} sayfasını kontrol edebilirsiniz.
+
+### Adım 5: İçeriği Geri Döndürün
+
+```Python hl_lines="8"
+{!../../../docs_src/first_steps/tutorial001.py!}
+```
+
+Bir `dict`, `list` veya `str`, `int` gibi tekil değerler döndürebilirsiniz.
+
+Ayrıca, Pydantic modelleri de döndürebilirsiniz (bu konu ileriki aşamalarda irdelenecektir).
+
+Otomatik olarak JSON'a dönüştürülecek (ORM'ler vb. dahil) başka birçok nesne ve model vardır. En beğendiklerinizi kullanmayı deneyin, yüksek ihtimalle destekleniyordur.
+
+## Özet
+
+* `FastAPI`'yı projemize dahil ettik.
+* Bir `app` örneği oluşturduk.
+* Bir **yol operasyonu dekoratörü** (`@app.get("/")` gibi) yazdık.
+* Bir **yol operasyonu fonksiyonu** (`def root(): ...` gibi) yazdık.
+* Geliştirme sunucumuzu (`uvicorn main:app --reload` gibi) çalıştırdık.
diff --git a/docs/tr/docs/tutorial/first_steps.md b/docs/tr/docs/tutorial/first_steps.md
deleted file mode 100644
index b39802f5d..000000000
--- a/docs/tr/docs/tutorial/first_steps.md
+++ /dev/null
@@ -1,336 +0,0 @@
-# İlk Adımlar
-
-En basit FastAPI dosyası şu şekildedir:
-
-```Python
-{!../../../docs_src/first_steps/tutorial001.py!}
-```
-
-Bunu bir `main.py` dosyasına kopyalayın.
-
-Projeyi çalıştırın:
-
-
-
-```console
-$ uvicorn main:app --reload
-
-INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
-INFO: Started reloader process [28720]
-INFO: Started server process [28722]
-INFO: Waiting for application startup.
-INFO: Application startup complete.
-```
-
-
-
-!!! note
- `uvicorn main:app` komutu şunu ifade eder:
-
- * `main`: `main.py` dosyası (the Python "module").
- * `app`: `main.py` dosyası içerisinde `app = FastAPI()` satırıyla oluşturulan nesne.
- * `--reload`: Kod değişikliği sonrasında sunucunun yeniden başlatılmasını sağlar. Yalnızca geliştirme için kullanın.
-
-Çıktıda şu şekilde bir satır vardır:
-
-```hl_lines="4"
-INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
-```
-
-Bu satır, yerel makinenizde uygulamanızın sunulduğu URL'yi gösterir.
-
-### Kontrol Et
-
-Tarayıcınızda
http://127.0.0.1:8000 adresini açın.
-
-Bir JSON yanıtı göreceksiniz:
-
-```JSON
-{"message": "Hello World"}
-```
-
-### İnteraktif API dokümantasyonu
-
-
http://127.0.0.1:8000/docs adresine gidin.
-
-Otomatik oluşturulmuş(
Swagger UI tarafından sağlanan) interaktif bir API dokümanı göreceksiniz:
-
-
-
-### Alternatif API dokümantasyonu
-
-Şimdi,
http://127.0.0.1:8000/redoc adresine gidin.
-
-Otomatik oluşturulmuş(
ReDoc tarafından sağlanan) bir API dokümanı göreceksiniz:
-
-
-
-### OpenAPI
-
-**FastAPI**, **OpenAPI** standardını kullanarak tüm API'lerinizi açıklayan bir "şema" oluşturur.
-
-#### "Şema"
-
-Bir "şema", bir şeyin tanımı veya açıklamasıdır. Soyut bir açıklamadır, uygulayan kod değildir.
-
-#### API "şemaları"
-
-Bu durumda,
OpenAPI, API şemasını nasıl tanımlayacağınızı belirten şartnamelerdir.
-
-Bu şema tanımı, API yollarınızı, aldıkları olası parametreleri vb. içerir.
-
-#### Data "şema"
-
-"Şema" terimi, JSON içeriği gibi bazı verilerin şeklini de ifade edebilir.
-
-Bu durumda, JSON öznitelikleri ve sahip oldukları veri türleri vb. anlamına gelir.
-
-#### OpenAPI and JSON Şema
-
-OpenAPI, API'niz için bir API şeması tanımlar. Ve bu şema, JSON veri şemaları standardı olan **JSON Şema** kullanılarak API'niz tarafından gönderilen ve alınan verilerin tanımlarını (veya "şemalarını") içerir.
-
-#### `openapi.json` kontrol et
-
-OpenAPI şemasının nasıl göründüğünü merak ediyorsanız, FastAPI otomatik olarak tüm API'nizin açıklamalarını içeren bir JSON (şema) oluşturur.
-
-Doğrudan şu adreste görebilirsiniz:
http://127.0.0.1:8000/openapi.json.
-
-Aşağıdaki gibi bir şeyle başlayan bir JSON gösterecektir:
-
-```JSON
-{
- "openapi": "3.0.2",
- "info": {
- "title": "FastAPI",
- "version": "0.1.0"
- },
- "paths": {
- "/items/": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {
- "application/json": {
-
-
-
-...
-```
-
-#### OpenAPI ne içindir?
-
-OpenAPI şeması, dahili olarak bulunan iki etkileşimli dokümantasyon sistemine güç veren şeydir.
-
-Ve tamamen OpenAPI'ye dayalı düzinelerce alternatif vardır. **FastAPI** ile oluşturulmuş uygulamanıza bu alternatiflerden herhangi birini kolayca ekleyebilirsiniz.
-
-API'nizle iletişim kuran istemciler için otomatik olarak kod oluşturmak için de kullanabilirsiniz. Örneğin, frontend, mobil veya IoT uygulamaları.
-
-## Adım adım özet
-
-### Adım 1: `FastAPI`yi içe aktarın
-
-```Python hl_lines="1"
-{!../../../docs_src/first_steps/tutorial001.py!}
-```
-
-`FastAPI`, API'niz için tüm fonksiyonları sağlayan bir Python sınıfıdır.
-
-!!! note "Teknik Detaylar"
- `FastAPI` doğrudan `Starlette` kalıtım alan bir sınıftır.
-
- Tüm
Starlette fonksiyonlarını `FastAPI` ile de kullanabilirsiniz.
-
-### Adım 2: Bir `FastAPI` örneği oluşturun
-
-```Python hl_lines="3"
-{!../../../docs_src/first_steps/tutorial001.py!}
-```
-
-Burada `app` değişkeni `FastAPI` sınıfının bir örneği olacaktır.
-
-Bu tüm API'yi oluşturmak için ana etkileşim noktası olacaktır.
-
-`uvicorn` komutunda atıfta bulunulan `app` ile aynıdır.
-
-
-
-```console
-$ uvicorn main:app --reload
-
-INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
-```
-
-
-
-Uygulamanızı aşağıdaki gibi oluşturursanız:
-
-```Python hl_lines="3"
-{!../../../docs_src/first_steps/tutorial002.py!}
-```
-
-Ve bunu `main.py` dosyasına koyduktan sonra `uvicorn` komutunu şu şekilde çağırabilirsiniz:
-
-
-
-```console
-$ uvicorn main:my_awesome_api --reload
-
-INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
-```
-
-
-
-### Adım 3: *Path işlemleri* oluşturmak
-
-#### Path
-
-Burada "Path" URL'de ilk "\" ile başlayan son bölümü ifade eder.
-
-Yani, şu şekilde bir URL'de:
-
-```
-https://example.com/items/foo
-```
-
-... path şöyle olabilir:
-
-```
-/items/foo
-```
-
-!!! info
- Genellikle bir "path", "endpoint" veya "route" olarak adlandırılabilir.
-
-Bir API oluştururken, "path", "resource" ile "concern" ayırmanın ana yoludur.
-
-#### İşlemler
-
-Burada "işlem" HTTP methodlarından birini ifade eder.
-
-Onlardan biri:
-
-* `POST`
-* `GET`
-* `PUT`
-* `DELETE`
-
-... ve daha egzotik olanları:
-
-* `OPTIONS`
-* `HEAD`
-* `PATCH`
-* `TRACE`
-
-HTTP protokolünde, bu "methodlardan" birini (veya daha fazlasını) kullanarak her path ile iletişim kurabilirsiniz.
-
----
-
-API'lerinizi oluştururkan, belirli bir işlemi gerçekleştirirken belirli HTTP methodlarını kullanırsınız.
-
-Normalde kullanılan:
-
-* `POST`: veri oluşturmak.
-* `GET`: veri okumak.
-* `PUT`: veriyi güncellemek.
-* `DELETE`: veriyi silmek.
-
-Bu nedenle, OpenAPI'de HTTP methodlarından her birine "işlem" denir.
-
-Bizde onlara "**işlemler**" diyeceğiz.
-
-#### Bir *Path işlem decoratorleri* tanımlanmak
-
-```Python hl_lines="6"
-{!../../../docs_src/first_steps/tutorial001.py!}
-```
-
-`@app.get("/")` **FastAPI'ye** aşağıdaki fonksiyonun adresine giden istekleri işlemekten sorumlu olduğunu söyler:
-
-* path `/`
-*
get
işlemi kullanılarak
-
-
-!!! info "`@decorator` Bilgisi"
- Python `@something` şeklinde ifadeleri "decorator" olarak adlandırır.
-
- Decoratoru bir fonksiyonun üzerine koyarsınız. Dekoratif bir şapka gibi (Sanırım terim buradan gelmektedir).
-
- Bir "decorator" fonksiyonu alır ve bazı işlemler gerçekleştir.
-
- Bizim durumumzda decarator **FastAPI'ye** fonksiyonun bir `get` işlemi ile `/` pathine geldiğini söyler.
-
- Bu **path işlem decoratordür**
-
-Ayrıca diğer işlemleri de kullanabilirsiniz:
-
-* `@app.post()`
-* `@app.put()`
-* `@app.delete()`
-
-Ve daha egzotik olanları:
-
-* `@app.options()`
-* `@app.head()`
-* `@app.patch()`
-* `@app.trace()`
-
-!!! tip
- Her işlemi (HTTP method) istediğiniz gibi kullanmakta özgürsünüz.
-
- **FastAPI** herhangi bir özel anlamı zorlamaz.
-
- Buradaki bilgiler bir gereklilik değil, bir kılavuz olarak sunulmaktadır.
-
- Örneğin, GraphQL kullanırkan normalde tüm işlemleri yalnızca `POST` işlemini kullanarak gerçekleştirirsiniz.
-
-### Adım 4: **path işlem fonksiyonunu** tanımlayın
-
-Aşağıdakiler bizim **path işlem fonksiyonlarımızdır**:
-
-* **path**: `/`
-* **işlem**: `get`
-* **function**: "decorator"ün altındaki fonksiyondur (`@app.get("/")` altında).
-
-```Python hl_lines="7"
-{!../../../docs_src/first_steps/tutorial001.py!}
-```
-
-Bu bir Python fonksiyonudur.
-
-Bir `GET` işlemi kullanarak "`/`" URL'sine bir istek geldiğinde **FastAPI** tarafından çağrılır.
-
-Bu durumda bir `async` fonksiyonudur.
-
----
-
-Bunu `async def` yerine normal bir fonksiyon olarakta tanımlayabilirsiniz.
-
-```Python hl_lines="7"
-{!../../../docs_src/first_steps/tutorial003.py!}
-```
-
-!!! note
-
- Eğer farkı bilmiyorsanız, [Async: *"Acelesi var?"*](../async.md#in-a-hurry){.internal-link target=_blank} kontrol edebilirsiniz.
-
-### Adım 5: İçeriği geri döndürün
-
-
-```Python hl_lines="8"
-{!../../../docs_src/first_steps/tutorial001.py!}
-```
-
-Bir `dict`, `list` döndürebilir veya `str`, `int` gibi tekil değerler döndürebilirsiniz.
-
-Ayrıca, Pydantic modellerini de döndürebilirsiniz. (Bununla ilgili daha sonra ayrıntılı bilgi göreceksiniz.)
-
-Otomatik olarak JSON'a dönüştürülecek(ORM'ler vb. dahil) başka birçok nesne ve model vardır. En beğendiklerinizi kullanmayı deneyin, yüksek ihtimalle destekleniyordur.
-
-## Özet
-
-* `FastAPI`'yi içe aktarın.
-* Bir `app` örneği oluşturun.
-* **path işlem decorator** yazın. (`@app.get("/")` gibi)
-* **path işlem fonksiyonu** yazın. (`def root(): ...` gibi)
-* Development sunucunuzu çalıştırın. (`uvicorn main:app --reload` gibi)
diff --git a/docs/tr/docs/tutorial/path-params.md b/docs/tr/docs/tutorial/path-params.md
new file mode 100644
index 000000000..c19023645
--- /dev/null
+++ b/docs/tr/docs/tutorial/path-params.md
@@ -0,0 +1,254 @@
+# Yol Parametreleri
+
+Yol "parametrelerini" veya "değişkenlerini" Python
string biçimlemede kullanılan sözdizimi ile tanımlayabilirsiniz.
+
+```Python hl_lines="6-7"
+{!../../../docs_src/path_params/tutorial001.py!}
+```
+
+Yol parametresi olan `item_id`'nin değeri, fonksiyonunuza `item_id` argümanı olarak aktarılacaktır.
+
+Eğer bu örneği çalıştırıp
http://127.0.0.1:8000/items/foo sayfasına giderseniz, şöyle bir çıktı ile karşılaşırsınız:
+
+```JSON
+{"item_id":"foo"}
+```
+
+## Tip İçeren Yol Parametreleri
+
+Standart Python tip belirteçlerini kullanarak yol parametresinin tipini fonksiyonun içerisinde tanımlayabilirsiniz.
+
+```Python hl_lines="7"
+{!../../../docs_src/path_params/tutorial002.py!}
+```
+
+Bu durumda, `item_id` bir `int` olarak tanımlanacaktır.
+
+!!! check "Ek bilgi"
+ Bu sayede, fonksiyon içerisinde hata denetimi, kod tamamlama gibi konularda editör desteğine kavuşacaksınız.
+
+## Veri
Dönüşümü
+
+Eğer bu örneği çalıştırıp tarayıcınızda
http://127.0.0.1:8000/items/3 sayfasını açarsanız, şöyle bir yanıt ile karşılaşırsınız:
+
+```JSON
+{"item_id":3}
+```
+
+!!! check "Ek bilgi"
+ Dikkatinizi çekerim ki, fonksiyonunuzun aldığı (ve döndürdüğü) değer olan `3` bir string `"3"` değil aksine bir Python `int`'idir.
+
+ Bu tanımlamayla birlikte, **FastAPI** size otomatik istek
"ayrıştırma" özelliği sağlar.
+
+## Veri Doğrulama
+
+Eğer tarayıcınızda
http://127.0.0.1:8000/items/foo sayfasını açarsanız, şuna benzer güzel bir HTTP hatası ile karşılaşırsınız:
+
+```JSON
+{
+ "detail": [
+ {
+ "type": "int_parsing",
+ "loc": [
+ "path",
+ "item_id"
+ ],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "foo",
+ "url": "https://errors.pydantic.dev/2.1/v/int_parsing"
+ }
+ ]
+}
+```
+
+Çünkü burada `item_id` yol parametresi `int` tipinde bir değer beklerken `"foo"` yani `string` tipinde bir değer almıştı.
+
+Aynı hata
http://127.0.0.1:8000/items/4.2 sayfasında olduğu gibi `int` yerine `float` bir değer verseydik de ortaya çıkardı.
+
+!!! check "Ek bilgi"
+ Böylece, aynı Python tip tanımlaması ile birlikte, **FastAPI** veri doğrulama özelliği sağlar.
+
+ Dikkatinizi çekerim ki, karşılaştığınız hata, doğrulamanın geçersiz olduğu mutlak noktayı da açık bir şekilde belirtiyor.
+
+ Bu özellik, API'ınızla iletişime geçen kodu geliştirirken ve ayıklarken inanılmaz derecede yararlı olacaktır.
+
+## Dokümantasyon
+
+Ayrıca, tarayıcınızı
http://127.0.0.1:8000/docs adresinde açarsanız, aşağıdaki gibi otomatik ve interaktif bir API dökümantasyonu ile karşılaşırsınız:
+
+

+
+!!! check "Ek bilgi"
+ Üstelik, sadece aynı Python tip tanımlaması ile, **FastAPI** size otomatik ve interaktif (Swagger UI ile entegre) bir dokümantasyon sağlar.
+
+ Dikkatinizi çekerim ki, yol parametresi integer olarak tanımlanmıştır.
+
+## Standartlara Dayalı Avantajlar, Alternatif Dokümantasyon
+
+Oluşturulan şema
OpenAPI standardına uygun olduğu için birçok uyumlu araç mevcuttur.
+
+Bu sayede, **FastAPI**'ın bizzat kendisi
http://127.0.0.1:8000/redoc sayfasından erişebileceğiniz alternatif (ReDoc kullanan) bir API dokümantasyonu sağlar:
+
+

+
+Aynı şekilde, farklı diller için kod türetme araçları da dahil olmak üzere çok sayıda uyumlu araç bulunur.
+
+## Pydantic
+
+Tüm veri doğrulamaları
Pydantic tarafından arka planda gerçekleştirilir, bu sayede tüm avantajlardan faydalanabilirsiniz. Böylece, emin ellerde olduğunuzu hissedebilirsiniz.
+
+Aynı tip tanımlamalarını `str`, `float`, `bool` ve diğer karmaşık veri tipleri ile kullanma imkanınız vardır.
+
+Bunlardan birkaçı, bu eğitimin ileriki bölümlerinde irdelenmiştir.
+
+## Sıralama Önem Arz Eder
+
+*Yol operasyonları* tasarlarken sabit yol barındıran durumlar ile karşılaşabilirsiniz.
+
+Farz edelim ki `/users/me` yolu geçerli kullanıcı hakkında bilgi almak için kullanılıyor olsun.
+
+Benzer şekilde `/users/{user_id}` gibi tanımlanmış ve belirli bir kullanıcı hakkında veri almak için kullanıcının ID bilgisini kullanan bir yolunuz da mevcut olabilir.
+
+*Yol operasyonları* sıralı bir şekilde gözden geçirildiğinden dolayı `/users/me` yolunun `/users/{user_id}` yolundan önce tanımlanmış olmasından emin olmanız gerekmektedir:
+
+```Python hl_lines="6 11"
+{!../../../docs_src/path_params/tutorial003.py!}
+```
+
+Aksi halde, `/users/{user_id}` yolu `"me"` değerinin `user_id` parametresi için gönderildiğini "düşünerek" `/users/me` ile de eşleşir.
+
+Benzer şekilde, bir yol operasyonunu yeniden tanımlamanız mümkün değildir:
+
+```Python hl_lines="6 11"
+{!../../../docs_src/path_params/tutorial003b.py!}
+```
+
+Yol, ilk kısım ile eşleştiğinden dolayı her koşulda ilk yol operasyonu kullanılacaktır.
+
+## Ön Tanımlı Değerler
+
+Eğer *yol parametresi* alan bir *yol operasyonunuz* varsa ve alabileceği *yol parametresi* değerlerinin ön tanımlı olmasını istiyorsanız, standart Python
`Enum` tipini kullanabilirsiniz.
+
+### Bir `Enum` Sınıfı Oluşturalım
+
+`Enum` sınıfını projemize dahil edip `str` ile `Enum` sınıflarını miras alan bir alt sınıf yaratalım.
+
+`str` sınıfı miras alındığından dolayı, API dokümanı, değerlerin `string` tipinde olması gerektiğini anlayabilecek ve doğru bir şekilde işlenecektir.
+
+Sonrasında, sınıf içerisinde, mevcut ve geçerli değerler olacak olan sabit değerli özelliklerini oluşturalım:
+
+```Python hl_lines="1 6-9"
+{!../../../docs_src/path_params/tutorial005.py!}
+```
+
+!!! info "Bilgi"
+ 3.4 sürümünden beri
enumerationlar (ya da enumlar) Python'da mevcuttur.
+
+!!! tip "İpucu"
+ Merak ediyorsanız söyleyeyim, "AlexNet", "ResNet" ve "LeNet" isimleri Makine Öğrenmesi
modellerini temsil eder.
+
+### Bir *Yol Parametresi* Tanımlayalım
+
+Sonrasında, yarattığımız enum sınıfını (`ModelName`) kullanarak tip belirteci aracılığıyla bir *yol parametresi* oluşturalım:
+
+```Python hl_lines="16"
+{!../../../docs_src/path_params/tutorial005.py!}
+```
+
+### Dokümana Göz Atalım
+
+*Yol parametresi* için mevcut değerler ön tanımlı olduğundan dolayı, interaktif döküman onları güzel bir şekilde gösterebilir:
+
+

+
+### Python *Enumerationları* ile Çalışmak
+
+*Yol parametresinin* değeri bir *enumeration üyesi* olacaktır.
+
+#### *Enumeration Üyelerini* Karşılaştıralım
+
+Parametreyi, yarattığınız enum olan `ModelName` içerisindeki *enumeration üyesi* ile karşılaştırabilirsiniz:
+
+```Python hl_lines="17"
+{!../../../docs_src/path_params/tutorial005.py!}
+```
+
+#### *Enumeration Değerini* Edinelim
+
+`model_name.value` veya genel olarak `your_enum_member.value` tanımlarını kullanarak (bu durumda bir `str` olan) gerçek değere ulaşabilirsiniz:
+
+```Python hl_lines="20"
+{!../../../docs_src/path_params/tutorial005.py!}
+```
+
+!!! tip "İpucu"
+ `"lenet"` değerine `ModelName.lenet.value` tanımı ile de ulaşabilirsiniz.
+
+#### *Enumeration Üyelerini* Döndürelim
+
+JSON gövdesine (örneğin bir `dict`) gömülü olsalar bile *yol operasyonundaki* *enum üyelerini* döndürebilirsiniz.
+
+Bu üyeler istemciye iletilmeden önce kendilerine karşılık gelen değerlerine (bu durumda string) dönüştürüleceklerdir:
+
+```Python hl_lines="18 21 23"
+{!../../../docs_src/path_params/tutorial005.py!}
+```
+
+İstemci tarafında şuna benzer bir JSON yanıtı ile karşılaşırsınız:
+
+```JSON
+{
+ "model_name": "alexnet",
+ "message": "Deep Learning FTW!"
+}
+```
+
+## Yol İçeren Yol Parametreleri
+
+Farz edelim ki elinizde `/files/{file_path}` isminde bir *yol operasyonu* var.
+
+Fakat `file_path` değerinin `home/johndoe/myfile.txt` gibi bir *yol* barındırmasını istiyorsunuz.
+
+Sonuç olarak, oluşturmak istediğin URL `/files/home/johndoe/myfile.txt` gibi bir şey olacaktır.
+
+### OpenAPI Desteği
+
+Test etmesi ve tanımlaması zor senaryolara sebebiyet vereceğinden dolayı OpenAPI, *yol* barındıran *yol parametrelerini* tanımlayacak bir çözüm sunmuyor.
+
+Ancak bunu, Starlette kütüphanesinin dahili araçlarından birini kullanarak **FastAPI**'da gerçekleştirebilirsiniz.
+
+Parametrenin bir yol içermesi gerektiğini belirten herhangi bir doküman eklemememize rağmen dokümanlar yine de çalışacaktır.
+
+### Yol Dönüştürücü
+
+Direkt olarak Starlette kütüphanesinden gelen bir opsiyon sayesinde aşağıdaki gibi *yol* içeren bir *yol parametresi* bağlantısı tanımlayabilirsiniz:
+
+```
+/files/{file_path:path}
+```
+
+Bu durumda, parametrenin adı `file_path` olacaktır ve son kısım olan `:path` kısmı, parametrenin herhangi bir *yol* ile eşleşmesi gerektiğini belirtecektir.
+
+Böylece şunun gibi bir kullanım yapabilirsiniz:
+
+```Python hl_lines="6"
+{!../../../docs_src/path_params/tutorial004.py!}
+```
+
+!!! tip "İpucu"
+ Parametrenin başında `/home/johndoe/myfile.txt` yolunda olduğu gibi (`/`) işareti ile birlikte kullanmanız gerektiği durumlar olabilir.
+
+ Bu durumda, URL, `files` ile `home` arasında iki eğik çizgiye (`//`) sahip olup `/files//home/johndoe/myfile.txt` gibi gözükecektir.
+
+## Özet
+
+**FastAPI** ile kısa, sezgisel ve standart Python tip tanımlamaları kullanarak şunları elde edersiniz:
+
+* Editör desteği: hata denetimi, otomatik tamamlama, vb.
+* Veri "
dönüştürme"
+* Veri doğrulama
+* API tanımlamaları ve otomatik dokümantasyon
+
+Ve sadece, bunları bir kez tanımlamanız yeterli.
+
+Diğer frameworkler ile karşılaştırıldığında (ham performans dışında), üstte anlatılan durum muhtemelen **FastAPI**'ın göze çarpan başlıca avantajıdır.
diff --git a/docs/tr/docs/tutorial/query-params.md b/docs/tr/docs/tutorial/query-params.md
new file mode 100644
index 000000000..aa3915557
--- /dev/null
+++ b/docs/tr/docs/tutorial/query-params.md
@@ -0,0 +1,227 @@
+# Sorgu Parametreleri
+
+Fonksiyonda yol parametrelerinin parçası olmayan diğer tanımlamalar otomatik olarak "sorgu" parametresi olarak yorumlanır.
+
+```Python hl_lines="9"
+{!../../../docs_src/query_params/tutorial001.py!}
+```
+
+Sorgu, bağlantıdaki `?` kısmından sonra gelen ve `&` işareti ile ayrılan anahtar-değer çiftlerinin oluşturduğu bir kümedir.
+
+Örneğin, aşağıdaki bağlantıda:
+
+```
+http://127.0.0.1:8000/items/?skip=0&limit=10
+```
+
+...sorgu parametreleri şunlardır:
+
+* `skip`: değeri `0`'dır
+* `limit`: değeri `10`'dır
+
+Parametreler bağlantının bir parçası oldukları için doğal olarak string olarak değerlendirilirler.
+
+Fakat, Python tipleri ile tanımlandıkları zaman (yukarıdaki örnekte `int` oldukları gibi), parametreler o tiplere dönüştürülür ve o tipler çerçevesinde doğrulanırlar.
+
+Yol parametreleri için geçerli olan her türlü işlem aynı şekilde sorgu parametreleri için de geçerlidir:
+
+* Editör desteği (şüphesiz)
+* Veri "
ayrıştırma"
+* Veri doğrulama
+* Otomatik dokümantasyon
+
+## Varsayılanlar
+
+Sorgu parametreleri, adres yolunun sabit bir parçası olmadıklarından dolayı isteğe bağlı ve varsayılan değere sahip olabilirler.
+
+Yukarıdaki örnekte `skip=0` ve `limit=10` varsayılan değere sahiplerdir.
+
+Yani, aşağıdaki bağlantıya gitmek:
+
+```
+http://127.0.0.1:8000/items/
+```
+
+şu adrese gitmek ile aynı etkiye sahiptir:
+
+```
+http://127.0.0.1:8000/items/?skip=0&limit=10
+```
+
+Ancak, mesela şöyle bir adresi ziyaret ederseniz:
+
+```
+http://127.0.0.1:8000/items/?skip=20
+```
+
+Fonksiyonunuzdaki parametre değerleri aşağıdaki gibi olacaktır:
+
+* `skip=20`: çünkü bağlantıda böyle tanımlandı.
+* `limit=10`: çünkü varsayılan değer buydu.
+
+## İsteğe Bağlı Parametreler
+
+Aynı şekilde, varsayılan değerlerini `None` olarak atayarak isteğe bağlı parametreler tanımlayabilirsiniz:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.8+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params/tutorial002.py!}
+ ```
+
+Bu durumda, `q` fonksiyon parametresi isteğe bağlı olacak ve varsayılan değer olarak `None` alacaktır.
+
+!!! check "Ek bilgi"
+ Ayrıca, dikkatinizi çekerim ki; **FastAPI**, `item_id` parametresinin bir yol parametresi olduğunu ve `q` parametresinin yol değil bir sorgu parametresi olduğunu fark edecek kadar beceriklidir.
+
+## Sorgu Parametresi Tip Dönüşümü
+
+Aşağıda görüldüğü gibi dönüştürülmek üzere `bool` tipleri de tanımlayabilirsiniz:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.8+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params/tutorial003.py!}
+ ```
+
+Bu durumda, eğer şu adrese giderseniz:
+
+```
+http://127.0.0.1:8000/items/foo?short=1
+```
+
+veya
+
+```
+http://127.0.0.1:8000/items/foo?short=True
+```
+
+veya
+
+```
+http://127.0.0.1:8000/items/foo?short=true
+```
+
+veya
+
+```
+http://127.0.0.1:8000/items/foo?short=on
+```
+
+veya
+
+```
+http://127.0.0.1:8000/items/foo?short=yes
+```
+
+veya adres, herhangi farklı bir harf varyasyonu içermesi durumuna rağmen (büyük harf, sadece baş harfi büyük kelime, vb.) fonksiyonunuz, `bool` tipli `short` parametresini `True` olarak algılayacaktır. Aksi halde `False` olarak algılanacaktır.
+
+
+## Çoklu Yol ve Sorgu Parametreleri
+
+**FastAPI** neyin ne olduğunu ayırt edebileceğinden dolayı aynı anda birden fazla yol ve sorgu parametresi tanımlayabilirsiniz.
+
+Ve parametreleri, herhangi bir sıraya koymanıza da gerek yoktur.
+
+İsimlerine göre belirleneceklerdir:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="6 8"
+ {!> ../../../docs_src/query_params/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.8+"
+
+ ```Python hl_lines="8 10"
+ {!> ../../../docs_src/query_params/tutorial004.py!}
+ ```
+
+## Zorunlu Sorgu Parametreleri
+
+Türü yol olmayan bir parametre (şu ana kadar sadece sorgu parametrelerini gördük) için varsayılan değer tanımlarsanız o parametre zorunlu olmayacaktır.
+
+Parametre için belirli bir değer atamak istemeyip parametrenin sadece isteğe bağlı olmasını istiyorsanız değerini `None` olarak atayabilirsiniz.
+
+Fakat, bir sorgu parametresini zorunlu yapmak istiyorsanız varsayılan bir değer atamamanız yeterli olacaktır:
+
+```Python hl_lines="6-7"
+{!../../../docs_src/query_params/tutorial005.py!}
+```
+
+Burada `needy` parametresi `str` tipinden oluşan zorunlu bir sorgu parametresidir.
+
+Eğer tarayıcınızda şu bağlantıyı:
+
+```
+http://127.0.0.1:8000/items/foo-item
+```
+
+...`needy` parametresini eklemeden açarsanız şuna benzer bir hata ile karşılaşırsınız:
+
+```JSON
+{
+ "detail": [
+ {
+ "type": "missing",
+ "loc": [
+ "query",
+ "needy"
+ ],
+ "msg": "Field required",
+ "input": null,
+ "url": "https://errors.pydantic.dev/2.1/v/missing"
+ }
+ ]
+}
+```
+
+`needy` zorunlu bir parametre olduğundan dolayı bağlantıda tanımlanması gerekir:
+
+```
+http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
+```
+
+...bu iş görür:
+
+```JSON
+{
+ "item_id": "foo-item",
+ "needy": "sooooneedy"
+}
+```
+
+Ve elbette, bazı parametreleri zorunlu, bazılarını varsayılan değerli ve bazılarını tamamen opsiyonel olarak tanımlayabilirsiniz:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params/tutorial006_py310.py!}
+ ```
+
+=== "Python 3.8+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params/tutorial006.py!}
+ ```
+
+Bu durumda, 3 tane sorgu parametresi var olacaktır:
+
+* `needy`, zorunlu bir `str`.
+* `skip`, varsayılan değeri `0` olan bir `int`.
+* `limit`, isteğe bağlı bir `int`.
+
+!!! tip "İpucu"
+ Ayrıca, [Yol Parametrelerinde](path-params.md#predefined-values){.internal-link target=_blank} de kullanıldığı şekilde `Enum` sınıfından faydalanabilirsiniz.
diff --git a/docs/uk/docs/alternatives.md b/docs/uk/docs/alternatives.md
index e71257976..bdb62513e 100644
--- a/docs/uk/docs/alternatives.md
+++ b/docs/uk/docs/alternatives.md
@@ -340,7 +340,7 @@ Hug був одним із перших фреймворків, який реа
## Використовується **FastAPI**
-###
Pydantic
+###
Pydantic
Pydantic — це бібліотека для визначення перевірки даних, серіалізації та документації (за допомогою схеми JSON) на основі підказок типу Python.
diff --git a/docs/uk/docs/fastapi-people.md b/docs/uk/docs/fastapi-people.md
index b32f0e5ce..f7d0220b5 100644
--- a/docs/uk/docs/fastapi-people.md
+++ b/docs/uk/docs/fastapi-people.md
@@ -40,7 +40,7 @@ FastAPI має дивовижну спільноту, яка вітає люде
{% if people %}
-{% for user in people.last_month_active %}
+{% for user in people.last_month_experts[:10] %}
{% endfor %}
@@ -58,7 +58,7 @@ FastAPI має дивовижну спільноту, яка вітає люде
{% if people %}
-{% for user in people.experts %}
+{% for user in people.experts[:50] %}
{% endfor %}
@@ -76,7 +76,7 @@ FastAPI має дивовижну спільноту, яка вітає люде
{% if people %}
-{% for user in people.top_contributors %}
+{% for user in people.top_contributors[:50] %}
{% endfor %}
@@ -100,7 +100,7 @@ FastAPI має дивовижну спільноту, яка вітає люде
{% if people %}
-{% for user in people.top_reviewers %}
+{% for user in people.top_translations_reviewers[:50] %}
{% endfor %}
diff --git a/docs/uk/docs/index.md b/docs/uk/docs/index.md
index fad693f79..32f1f544a 100644
--- a/docs/uk/docs/index.md
+++ b/docs/uk/docs/index.md
@@ -115,7 +115,7 @@ Python 3.8+
FastAPI стоїть на плечах гігантів:
*
Starlette для web частини.
-*
Pydantic для частини даних.
+*
Pydantic для частини даних.
## Вставновлення
@@ -448,7 +448,7 @@ Starlette використовує:
*
httpx
- Необхідно, якщо Ви хочете використовувати `TestClient`.
*
jinja2
- Необхідно, якщо Ви хочете використовувати шаблони як конфігурацію за замовчуванням.
-*
python-multipart
- Необхідно, якщо Ви хочете підтримувати
"розбір" форми за допомогою `request.form()`.
+*
python-multipart
- Необхідно, якщо Ви хочете підтримувати
"розбір" форми за допомогою `request.form()`.
*
itsdangerous
- Необхідно для підтримки `SessionMiddleware`.
*
pyyaml
- Необхідно для підтримки Starlette `SchemaGenerator` (ймовірно, вам це не потрібно з FastAPI).
*
ujson
- Необхідно, якщо Ви хочете використовувати `UJSONResponse`.
diff --git a/docs/uk/docs/python-types.md b/docs/uk/docs/python-types.md
index 6c8e29016..e767db2fb 100644
--- a/docs/uk/docs/python-types.md
+++ b/docs/uk/docs/python-types.md
@@ -385,7 +385,7 @@ John Doe
## Pydantic моделі
-
Pydantic це бібліотека Python для валідації даних.
+
Pydantic це бібліотека Python для валідації даних.
Ви оголошуєте «форму» даних як класи з атрибутами.
@@ -416,7 +416,7 @@ John Doe
```
!!! info
- Щоб дізнатись більше про
Pydantic, перегляньте його документацію.
+ Щоб дізнатись більше про
Pydantic, перегляньте його документацію.
**FastAPI** повністю базується на Pydantic.
diff --git a/docs/uk/docs/tutorial/body.md b/docs/uk/docs/tutorial/body.md
index 9759e7f45..11e94e929 100644
--- a/docs/uk/docs/tutorial/body.md
+++ b/docs/uk/docs/tutorial/body.md
@@ -6,7 +6,7 @@
Ваш API майже завжди має надсилати тіло **відповіді**. Але клієнтам не обов’язково потрібно постійно надсилати тіла **запитів**.
-Щоб оголосити тіло **запиту**, ви використовуєте
Pydantic моделі з усією їх потужністю та перевагами.
+Щоб оголосити тіло **запиту**, ви використовуєте
Pydantic моделі з усією їх потужністю та перевагами.
!!! info
Щоб надіслати дані, ви повинні використовувати один із: `POST` (більш поширений), `PUT`, `DELETE` або `PATCH`.
diff --git a/docs/uk/docs/tutorial/extra-data-types.md b/docs/uk/docs/tutorial/extra-data-types.md
index ec5ec0d18..01852803a 100644
--- a/docs/uk/docs/tutorial/extra-data-types.md
+++ b/docs/uk/docs/tutorial/extra-data-types.md
@@ -36,7 +36,7 @@
* `datetime.timedelta`:
* Пайтонівський `datetime.timedelta`.
* У запитах та відповідях буде представлений як `float` загальної кількості секунд.
- * Pydantic також дозволяє представляти це як "ISO 8601 time diff encoding",
більше інформації дивись у документації.
+ * Pydantic також дозволяє представляти це як "ISO 8601 time diff encoding",
більше інформації дивись у документації.
* `frozenset`:
* У запитах і відповідях це буде оброблено так само, як і `set`:
* У запитах список буде зчитано, дублікати будуть видалені та він буде перетворений на `set`.
@@ -49,7 +49,7 @@
* `Decimal`:
* Стандартний Пайтонівський `Decimal`.
* У запитах і відповідях це буде оброблено так само, як і `float`.
-* Ви можете перевірити всі дійсні типи даних Pydantic тут:
типи даних Pydantic.
+* Ви можете перевірити всі дійсні типи даних Pydantic тут:
типи даних Pydantic.
## Приклад
diff --git a/docs/vi/docs/features.md b/docs/vi/docs/features.md
index 306aeb359..9edb1c8fa 100644
--- a/docs/vi/docs/features.md
+++ b/docs/vi/docs/features.md
@@ -172,7 +172,7 @@ Với **FastAPI**, bạn có được tất cả những tính năng của **Sta
## Tính năng của Pydantic
-**FastAPI** tương thích đầy đủ với (và dựa trên)
Pydantic. Do đó, bất kì code Pydantic nào bạn thêm vào cũng sẽ hoạt động.
+**FastAPI** tương thích đầy đủ với (và dựa trên)
Pydantic. Do đó, bất kì code Pydantic nào bạn thêm vào cũng sẽ hoạt động.
Bao gồm các thư viện bên ngoài cũng dựa trên Pydantic, như
ORMs,
ODMs cho cơ sở dữ liệu.
diff --git a/docs/vi/docs/index.md b/docs/vi/docs/index.md
index 3f416dbec..3ade853e2 100644
--- a/docs/vi/docs/index.md
+++ b/docs/vi/docs/index.md
@@ -121,7 +121,7 @@ Python 3.8+
FastAPI đứng trên vai những người khổng lồ:
*
Starlette cho phần web.
-*
Pydantic cho phần data.
+*
Pydantic cho phần data.
## Cài đặt
@@ -455,7 +455,7 @@ Sử dụng Starlette:
*
httpx
- Bắt buộc nếu bạn muốn sử dụng `TestClient`.
*
jinja2
- Bắt buộc nếu bạn muốn sử dụng cấu hình template engine mặc định.
-*
python-multipart
- Bắt buộc nếu bạn muốn hỗ trợ
"parsing", form với `request.form()`.
+*
python-multipart
- Bắt buộc nếu bạn muốn hỗ trợ
"parsing", form với `request.form()`.
*
itsdangerous
- Bắt buộc để hỗ trợ `SessionMiddleware`.
*
pyyaml
- Bắt buộc để hỗ trợ `SchemaGenerator` cho Starlette (bạn có thể không cần nó trong FastAPI).
*
ujson
- Bắt buộc nếu bạn muốn sử dụng `UJSONResponse`.
diff --git a/docs/vi/docs/python-types.md b/docs/vi/docs/python-types.md
index 4999caac3..b2a399aa5 100644
--- a/docs/vi/docs/python-types.md
+++ b/docs/vi/docs/python-types.md
@@ -440,7 +440,7 @@ Nó không có nghĩa "`one_person`" là một **lớp** gọi là `Person`.
## Pydantic models
-
Pydantic là một thư viện Python để validate dữ liệu hiệu năng cao.
+
Pydantic là một thư viện Python để validate dữ liệu hiệu năng cao.
Bạn có thể khai báo "hình dạng" của dữa liệu như là các lớp với các thuộc tính.
@@ -471,14 +471,14 @@ Một ví dụ từ tài liệu chính thức của Pydantic:
```
!!! info
- Để học nhiều hơn về
Pydantic, tham khảo tài liệu của nó.
+ Để học nhiều hơn về
Pydantic, tham khảo tài liệu của nó.
**FastAPI** được dựa hoàn toàn trên Pydantic.
Bạn sẽ thấy nhiều ví dụ thực tế hơn trong [Hướng dẫn sử dụng](tutorial/index.md){.internal-link target=_blank}.
!!! tip
- Pydantic có một hành vi đặc biệt khi bạn sử dụng `Optional` hoặc `Union[Something, None]` mà không có giá trị mặc dịnh, bạn có thể đọc nhiều hơn về nó trong tài liệu của Pydantic về
Required Optional fields.
+ Pydantic có một hành vi đặc biệt khi bạn sử dụng `Optional` hoặc `Union[Something, None]` mà không có giá trị mặc dịnh, bạn có thể đọc nhiều hơn về nó trong tài liệu của Pydantic về
Required Optional fields.
## Type Hints với Metadata Annotations
diff --git a/docs/yo/docs/index.md b/docs/yo/docs/index.md
index 101e13b6b..5684f0a6a 100644
--- a/docs/yo/docs/index.md
+++ b/docs/yo/docs/index.md
@@ -120,7 +120,7 @@ Python 3.8+
FastAPI dúró lórí àwọn èjìká tí àwọn òmíràn:
*
Starlette fún àwọn ẹ̀yà ayélujára.
-*
Pydantic fún àwọn ẹ̀yà àkójọf'áyẹ̀wò.
+*
Pydantic fún àwọn ẹ̀yà àkójọf'áyẹ̀wò.
## Fifi sórí ẹrọ
@@ -453,7 +453,7 @@ Láti ní òye síi nípa rẹ̀, wo abala àwọn
httpx
- Nílò tí ó bá fẹ́ láti lọ `TestClient`.
*
jinja2
- Nílò tí ó bá fẹ́ láti lọ iṣeto awoṣe aiyipada.
-*
python-multipart
- Nílò tí ó bá fẹ́ láti ṣe àtìlẹ́yìn fún
"àyẹ̀wò" fọọmu, pẹ̀lú `request.form()`.
+*
python-multipart
- Nílò tí ó bá fẹ́ láti ṣe àtìlẹ́yìn fún
"àyẹ̀wò" fọọmu, pẹ̀lú `request.form()`.
*
itsdangerous
- Nílò fún àtìlẹ́yìn `SessionMiddleware`.
*
pyyaml
- Nílò fún àtìlẹ́yìn Starlette's `SchemaGenerator` (ó ṣe ṣe kí ó má nílò rẹ̀ fún FastAPI).
*
ujson
- Nílò tí ó bá fẹ́ láti lọ `UJSONResponse`.
diff --git a/docs/zh-hant/docs/index.md b/docs/zh-hant/docs/index.md
index e7a2efec9..9859d3c51 100644
--- a/docs/zh-hant/docs/index.md
+++ b/docs/zh-hant/docs/index.md
@@ -120,7 +120,7 @@ Python 3.8+
FastAPI 是站在以下巨人的肩膀上:
-
Starlette 負責網頁的部分
--
Pydantic 負責資料的部分
+-
Pydantic 負責資料的部分
## 安裝
@@ -453,7 +453,7 @@ item: Item
-
httpx
- 使用 `TestClient`時必須安裝。
-
jinja2
- 使用預設的模板配置時必須安裝。
--
python-multipart
- 需要使用 `request.form()` 對表單進行
"解析" 時安裝。
+-
python-multipart
- 需要使用 `request.form()` 對表單進行
"解析" 時安裝。
-
itsdangerous
- 需要使用 `SessionMiddleware` 支援時安裝。
-
pyyaml
- 用於支援 Starlette 的 `SchemaGenerator` (如果你使用 FastAPI,可能不需要它)。
-
ujson
- 使用 `UJSONResponse` 時必須安裝。
diff --git a/docs/zh-hant/docs/learn/index.md b/docs/zh-hant/docs/learn/index.md
new file mode 100644
index 000000000..eb7d7096a
--- /dev/null
+++ b/docs/zh-hant/docs/learn/index.md
@@ -0,0 +1,5 @@
+# 學習
+
+以下是學習 FastAPI 的入門介紹和教學。
+
+你可以將其視為一本**書籍**或一門**課程**,這是**官方**認可並推薦的 FastAPI 學習方式。 😎
diff --git a/docs/zh/docs/advanced/dataclasses.md b/docs/zh/docs/advanced/dataclasses.md
new file mode 100644
index 000000000..5a93877cc
--- /dev/null
+++ b/docs/zh/docs/advanced/dataclasses.md
@@ -0,0 +1,99 @@
+# 使用数据类
+
+FastAPI 基于 **Pydantic** 构建,前文已经介绍过如何使用 Pydantic 模型声明请求与响应。
+
+但 FastAPI 还可以使用数据类(
`dataclasses`):
+
+```Python hl_lines="1 7-12 19-20"
+{!../../../docs_src/dataclasses/tutorial001.py!}
+```
+
+这还是借助于 **Pydantic** 及其
内置的 `dataclasses`。
+
+因此,即便上述代码没有显式使用 Pydantic,FastAPI 仍会使用 Pydantic 把标准数据类转换为 Pydantic 数据类(`dataclasses`)。
+
+并且,它仍然支持以下功能:
+
+* 数据验证
+* 数据序列化
+* 数据存档等
+
+数据类的和运作方式与 Pydantic 模型相同。实际上,它的底层使用的也是 Pydantic。
+
+!!! info "说明"
+
+ 注意,数据类不支持 Pydantic 模型的所有功能。
+
+ 因此,开发时仍需要使用 Pydantic 模型。
+
+ 但如果数据类很多,这一技巧能给 FastAPI 开发 Web API 增添不少助力。🤓
+
+## `response_model` 使用数据类
+
+在 `response_model` 参数中使用 `dataclasses`:
+
+```Python hl_lines="1 7-13 19"
+{!../../../docs_src/dataclasses/tutorial002.py!}
+```
+
+本例把数据类自动转换为 Pydantic 数据类。
+
+API 文档中也会显示相关概图:
+
+

+
+## 在嵌套数据结构中使用数据类
+
+您还可以把 `dataclasses` 与其它类型注解组合在一起,创建嵌套数据结构。
+
+还有一些情况也可以使用 Pydantic 的 `dataclasses`。例如,在 API 文档中显示错误。
+
+本例把标准的 `dataclasses` 直接替换为 `pydantic.dataclasses`:
+
+```{ .python .annotate hl_lines="1 5 8-11 14-17 23-25 28" }
+{!../../../docs_src/dataclasses/tutorial003.py!}
+```
+
+1. 本例依然要从标准的 `dataclasses` 中导入 `field`;
+
+2. 使用 `pydantic.dataclasses` 直接替换 `dataclasses`;
+
+3. `Author` 数据类包含 `Item` 数据类列表;
+
+4. `Author` 数据类用于 `response_model` 参数;
+
+5. 其它带有数据类的标准类型注解也可以作为请求体;
+
+ 本例使用的是 `Item` 数据类列表;
+
+6. 这行代码返回的是包含 `items` 的字典,`items` 是数据类列表;
+
+ FastAPI 仍能把数据
序列化为 JSON;
+
+7. 这行代码中,`response_model` 的类型注解是 `Author` 数据类列表;
+
+ 再一次,可以把 `dataclasses` 与标准类型注解一起使用;
+
+8. 注意,*路径操作函数*使用的是普通函数,不是异步函数;
+
+ 与往常一样,在 FastAPI 中,可以按需组合普通函数与异步函数;
+
+ 如果不清楚何时使用异步函数或普通函数,请参阅**急不可待?**一节中对
`async` 与 `await` 的说明;
+
+9. *路径操作函数*返回的不是数据类(虽然它可以返回数据类),而是返回内含数据的字典列表;
+
+ FastAPI 使用(包含数据类的) `response_model` 参数转换响应。
+
+把 `dataclasses` 与其它类型注解组合在一起,可以组成不同形式的复杂数据结构。
+
+更多内容详见上述代码内的注释。
+
+## 深入学习
+
+您还可以把 `dataclasses` 与其它 Pydantic 模型组合在一起,继承合并的模型,把它们包含在您自己的模型里。
+
+详见
Pydantic 官档 - 数据类。
+
+## 版本
+
+本章内容自 FastAPI `0.67.0` 版起生效。🔖
diff --git a/docs/zh/docs/advanced/index.md b/docs/zh/docs/advanced/index.md
index 824f91f47..e39eed805 100644
--- a/docs/zh/docs/advanced/index.md
+++ b/docs/zh/docs/advanced/index.md
@@ -2,7 +2,7 @@
## 额外特性
-主要的教程 [教程 - 用户指南](../tutorial/){.internal-link target=_blank} 应该足以让你了解 **FastAPI** 的所有主要特性。
+主要的教程 [教程 - 用户指南](../tutorial/index.md){.internal-link target=_blank} 应该足以让你了解 **FastAPI** 的所有主要特性。
你会在接下来的章节中了解到其他的选项、配置以及额外的特性。
@@ -13,6 +13,6 @@
## 先阅读教程
-你可能仍会用到 **FastAPI** 主教程 [教程 - 用户指南](../tutorial/){.internal-link target=_blank} 中的大多数特性。
+你可能仍会用到 **FastAPI** 主教程 [教程 - 用户指南](../tutorial/index.md){.internal-link target=_blank} 中的大多数特性。
-接下来的章节我们认为你已经读过 [教程 - 用户指南](../tutorial/){.internal-link target=_blank},并且假设你已经知晓其中主要思想。
+接下来的章节我们认为你已经读过 [教程 - 用户指南](../tutorial/index.md){.internal-link target=_blank},并且假设你已经知晓其中主要思想。
diff --git a/docs/zh/docs/advanced/middleware.md b/docs/zh/docs/advanced/middleware.md
new file mode 100644
index 000000000..06232fe17
--- /dev/null
+++ b/docs/zh/docs/advanced/middleware.md
@@ -0,0 +1,100 @@
+# 高级中间件
+
+用户指南介绍了如何为应用添加[自定义中间件](../tutorial/middleware.md){.internal-link target=_blank} 。
+
+以及如何[使用 `CORSMiddleware` 处理 CORS](../tutorial/cors.md){.internal-link target=_blank}。
+
+本章学习如何使用其它中间件。
+
+## 添加 ASGI 中间件
+
+因为 **FastAPI** 基于 Starlette,且执行
ASGI 规范,所以可以使用任意 ASGI 中间件。
+
+中间件不必是专为 FastAPI 或 Starlette 定制的,只要遵循 ASGI 规范即可。
+
+总之,ASGI 中间件是类,并把 ASGI 应用作为第一个参数。
+
+因此,有些第三方 ASGI 中间件的文档推荐以如下方式使用中间件:
+
+```Python
+from unicorn import UnicornMiddleware
+
+app = SomeASGIApp()
+
+new_app = UnicornMiddleware(app, some_config="rainbow")
+```
+
+但 FastAPI(实际上是 Starlette)提供了一种更简单的方式,能让内部中间件在处理服务器错误的同时,还能让自定义异常处理器正常运作。
+
+为此,要使用 `app.add_middleware()` (与 CORS 中的示例一样)。
+
+```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` 中提供的中间件只是为了方便开发者使用,但绝大多数可用的中间件都直接继承自 Starlette。
+
+## `HTTPSRedirectMiddleware`
+
+强制所有传入请求必须是 `https` 或 `wss`。
+
+任何传向 `http` 或 `ws` 的请求都会被重定向至安全方案。
+
+```Python hl_lines="2 6"
+{!../../../docs_src/advanced_middleware/tutorial001.py!}
+```
+
+## `TrustedHostMiddleware`
+
+强制所有传入请求都必须正确设置 `Host` 请求头,以防 HTTP 主机头攻击。
+
+```Python hl_lines="2 6-8"
+{!../../../docs_src/advanced_middleware/tutorial002.py!}
+```
+
+支持以下参数:
+
+* `allowed_hosts` - 允许的域名(主机名)列表。`*.example.com` 等通配符域名可以匹配子域名,或使用 `allowed_hosts=["*"]` 允许任意主机名,或省略中间件。
+
+如果传入的请求没有通过验证,则发送 `400` 响应。
+
+## `GZipMiddleware`
+
+处理 `Accept-Encoding` 请求头中包含 `gzip` 请求的 GZip 响应。
+
+中间件会处理标准响应与流响应。
+
+```Python hl_lines="2 6"
+{!../../../docs_src/advanced_middleware/tutorial003.py!}
+```
+
+支持以下参数:
+
+* `minimum_size` - 小于最小字节的响应不使用 GZip。 默认值是 `500`。
+
+## 其它中间件
+
+除了上述中间件外,FastAPI 还支持其它ASGI 中间件。
+
+例如:
+
+*
Sentry
+*
Uvicorn 的 `ProxyHeadersMiddleware`
+*
MessagePack
+
+其它可用中间件详见
Starlette 官档 - 中间件 及
ASGI Awesome 列表。
diff --git a/docs/zh/docs/advanced/openapi-callbacks.md b/docs/zh/docs/advanced/openapi-callbacks.md
new file mode 100644
index 000000000..e2dadbfb0
--- /dev/null
+++ b/docs/zh/docs/advanced/openapi-callbacks.md
@@ -0,0 +1,184 @@
+# OpenAPI 回调
+
+您可以创建触发外部 API 请求的*路径操作* API,这个外部 API 可以是别人创建的,也可以是由您自己创建的。
+
+API 应用调用外部 API 时的流程叫做**回调**。因为外部开发者编写的软件发送请求至您的 API,然后您的 API 要进行回调,并把请求发送至外部 API。
+
+此时,我们需要存档外部 API 的*信息*,比如应该有哪些*路径操作*,返回什么样的请求体,应该返回哪种响应等。
+
+## 使用回调的应用
+
+示例如下。
+
+假设要开发一个创建发票的应用。
+
+发票包括 `id`、`title`(可选)、`customer`、`total` 等属性。
+
+API 的用户 (外部开发者)要在您的 API 内使用 POST 请求创建一条发票记录。
+
+(假设)您的 API 将:
+
+* 把发票发送至外部开发者的消费者
+* 归集现金
+* 把通知发送至 API 的用户(外部开发者)
+ * 通过(从您的 API)发送 POST 请求至外部 API (即**回调**)来完成
+
+## 常规 **FastAPI** 应用
+
+添加回调前,首先看下常规 API 应用是什么样子。
+
+常规 API 应用包含接收 `Invoice` 请求体的*路径操作*,还有包含回调 URL 的查询参数 `callback_url`。
+
+这部分代码很常规,您对绝大多数代码应该都比较熟悉了:
+
+```Python hl_lines="10-14 37-54"
+{!../../../docs_src/openapi_callbacks/tutorial001.py!}
+```
+
+!!! tip "提示"
+
+ `callback_url` 查询参数使用 Pydantic 的
URL 类型。
+
+此处唯一比较新的内容是*路径操作装饰器*中的 `callbacks=invoices_callback_router.routes` 参数,下文介绍。
+
+## 存档回调
+
+实际的回调代码高度依赖于您自己的 API 应用。
+
+并且可能每个应用都各不相同。
+
+回调代码可能只有一两行,比如:
+
+```Python
+callback_url = "https://example.com/api/v1/invoices/events/"
+requests.post(callback_url, json={"description": "Invoice paid", "paid": True})
+```
+
+但回调最重要的部分可能是,根据 API 要发送给回调请求体的数据等内容,确保您的 API 用户(外部开发者)正确地实现*外部 API*。
+
+因此,我们下一步要做的就是添加代码,为从 API 接收回调的*外部 API*存档。
+
+这部分文档在 `/docs` 下的 Swagger API 文档中显示,并且会告诉外部开发者如何构建*外部 API*。
+
+本例没有实现回调本身(只是一行代码),只有文档部分。
+
+!!! tip "提示"
+
+ 实际的回调只是 HTTP 请求。
+
+ 实现回调时,要使用
HTTPX 或
Requests。
+
+## 编写回调文档代码
+
+应用不执行这部分代码,只是用它来*记录 外部 API* 。
+
+但,您已经知道用 **FastAPI** 创建自动 API 文档有多简单了。
+
+我们要使用与存档*外部 API* 相同的知识……通过创建外部 API 要实现的*路径操作*(您的 API 要调用的)。
+
+!!! tip "提示"
+
+ 编写存档回调的代码时,假设您是*外部开发者*可能会用的上。并且您当前正在实现的是*外部 API*,不是*您自己的 API*。
+
+ 临时改变(为外部开发者的)视角能让您更清楚该如何放置*外部 API* 响应和请求体的参数与 Pydantic 模型等。
+
+### 创建回调的 `APIRouter`
+
+首先,新建包含一些用于回调的 `APIRouter`。
+
+```Python hl_lines="5 26"
+{!../../../docs_src/openapi_callbacks/tutorial001.py!}
+```
+
+### 创建回调*路径操作*
+
+创建回调*路径操作*也使用之前创建的 `APIRouter`。
+
+它看起来和常规 FastAPI *路径操作*差不多:
+
+* 声明要接收的请求体,例如,`body: InvoiceEvent`
+* 还要声明要返回的响应,例如,`response_model=InvoiceEventReceived`
+
+```Python hl_lines="17-19 22-23 29-33"
+{!../../../docs_src/openapi_callbacks/tutorial001.py!}
+```
+
+回调*路径操作*与常规*路径操作*有两点主要区别:
+
+* 它不需要任何实际的代码,因为应用不会调用这段代码。它只是用于存档*外部 API*。因此,函数的内容只需要 `pass` 就可以了
+* *路径*可以包含
OpenAPI 3 表达式(详见下文),可以使用带参数的变量,以及发送至您的 API 的原始请求的部分
+
+### 回调路径表达式
+
+回调*路径*支持包含发送给您的 API 的原始请求的部分的
OpenAPI 3 表达式。
+
+本例中是**字符串**:
+
+```Python
+"{$callback_url}/invoices/{$request.body.id}"
+```
+
+因此,如果您的 API 用户(外部开发者)发送请求到您的 API:
+
+```
+https://yourapi.com/invoices/?callback_url=https://www.external.org/events
+```
+
+使用如下 JSON 请求体:
+
+```JSON
+{
+ "id": "2expen51ve",
+ "customer": "Mr. Richie Rich",
+ "total": "9999"
+}
+```
+
+然后,您的 API 就会处理发票,并在某个点之后,发送回调请求至 `callback_url`(外部 API):
+
+```
+https://www.external.org/events/invoices/2expen51ve
+```
+
+JSON 请求体包含如下内容:
+
+```JSON
+{
+ "description": "Payment celebration",
+ "paid": true
+}
+```
+
+它会预期*外部 API* 的响应包含如下 JSON 请求体:
+
+```JSON
+{
+ "ok": true
+}
+```
+
+!!! tip "提示"
+
+ 注意,回调 URL包含 `callback_url` (`https://www.external.org/events`)中的查询参数,还有 JSON 请求体内部的发票 ID(`2expen51ve`)。
+
+### 添加回调路由
+
+至此,在上文创建的回调路由里就包含了*回调路径操作*(外部开发者要在外部 API 中实现)。
+
+现在使用 API *路径操作装饰器*的参数 `callbacks`,从回调路由传递属性 `.routes`(实际上只是路由/路径操作的**列表**):
+
+```Python hl_lines="36"
+{!../../../docs_src/openapi_callbacks/tutorial001.py!}
+```
+
+!!! tip "提示"
+
+ 注意,不能把路由本身(`invoices_callback_router`)传递给 `callback=`,要传递 `invoices_callback_router.routes` 中的 `.routes` 属性。
+
+### 查看文档
+
+现在,使用 Uvicorn 启动应用,打开
http://127.0.0.1:8000/docs。
+
+就能看到文档的*路径操作*已经包含了**回调**的内容以及*外部 API*:
+
+

diff --git a/docs/zh/docs/advanced/security/http-basic-auth.md b/docs/zh/docs/advanced/security/http-basic-auth.md
new file mode 100644
index 000000000..1f251ca45
--- /dev/null
+++ b/docs/zh/docs/advanced/security/http-basic-auth.md
@@ -0,0 +1,107 @@
+# HTTP 基础授权
+
+最简单的用例是使用 HTTP 基础授权(HTTP Basic Auth)。
+
+在 HTTP 基础授权中,应用需要请求头包含用户名与密码。
+
+如果没有接收到 HTTP 基础授权,就返回 HTTP 401 `"Unauthorized"` 错误。
+
+并返回含 `Basic` 值的请求头 `WWW-Authenticate`以及可选的 `realm` 参数。
+
+HTTP 基础授权让浏览器显示内置的用户名与密码提示。
+
+输入用户名与密码后,浏览器会把它们自动发送至请求头。
+
+## 简单的 HTTP 基础授权
+
+* 导入 `HTTPBsic` 与 `HTTPBasicCredentials`
+* 使用 `HTTPBsic` 创建**安全概图**
+* 在*路径操作*的依赖项中使用 `security`
+* 返回类型为 `HTTPBasicCredentials` 的对象:
+ * 包含发送的 `username` 与 `password`
+
+```Python hl_lines="2 6 10"
+{!../../../docs_src/security/tutorial006.py!}
+```
+
+第一次打开 URL(或在 API 文档中点击 **Execute** 按钮)时,浏览器要求输入用户名与密码:
+
+

+
+## 检查用户名
+
+以下是更完整的示例。
+
+使用依赖项检查用户名与密码是否正确。
+
+为此要使用 Python 标准模块
`secrets` 检查用户名与密码:
+
+```Python hl_lines="1 11-13"
+{!../../../docs_src/security/tutorial007.py!}
+```
+
+这段代码确保 `credentials.username` 是 `"stanleyjobson"`,且 `credentials.password` 是`"swordfish"`。与以下代码类似:
+
+```Python
+if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"):
+ # Return some error
+ ...
+```
+
+但使用 `secrets.compare_digest()`,可以防御**时差攻击**,更加安全。
+
+### 时差攻击
+
+什么是**时差攻击**?
+
+假设攻击者试图猜出用户名与密码。
+
+他们发送用户名为 `johndoe`,密码为 `love123` 的请求。
+
+然后,Python 代码执行如下操作:
+
+```Python
+if "johndoe" == "stanleyjobson" and "love123" == "swordfish":
+ ...
+```
+
+但就在 Python 比较完 `johndoe` 的第一个字母 `j` 与 `stanleyjobson` 的 `s` 时,Python 就已经知道这两个字符串不相同了,它会这么想,**没必要浪费更多时间执行剩余字母的对比计算了**。应用立刻就会返回**错误的用户或密码**。
+
+但接下来,攻击者继续尝试 `stanleyjobsox` 和 密码 `love123`。
+
+应用代码会执行类似下面的操作:
+
+```Python
+if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish":
+ ...
+```
+
+此时,Python 要对比 `stanleyjobsox` 与 `stanleyjobson` 中的 `stanleyjobso`,才能知道这两个字符串不一样。因此会多花费几微秒来返回**错误的用户或密码**。
+
+#### 反应时间对攻击者的帮助
+
+通过服务器花费了更多微秒才发送**错误的用户或密码**响应,攻击者会知道猜对了一些内容,起码开头字母是正确的。
+
+然后,他们就可以放弃 `johndoe`,再用类似 `stanleyjobsox` 的内容进行尝试。
+
+#### **专业**攻击
+
+当然,攻击者不用手动操作,而是编写每秒能执行成千上万次测试的攻击程序,每次都会找到更多正确字符。
+
+但是,在您的应用的**帮助**下,攻击者利用时间差,就能在几分钟或几小时内,以这种方式猜出正确的用户名和密码。
+
+#### 使用 `secrets.compare_digest()` 修补
+
+在此,代码中使用了 `secrets.compare_digest()`。
+
+简单的说,它使用相同的时间对比 `stanleyjobsox` 和 `stanleyjobson`,还有 `johndoe` 和 `stanleyjobson`。对比密码时也一样。
+
+在代码中使用 `secrets.compare_digest()` ,就可以安全地防御全面攻击了。
+
+### 返回错误
+
+检测到凭证不正确后,返回 `HTTPException` 及状态码 401(与无凭证时返回的内容一样),并添加请求头 `WWW-Authenticate`,让浏览器再次显示登录提示:
+
+```Python hl_lines="15-19"
+{!../../../docs_src/security/tutorial007.py!}
+```
diff --git a/docs/zh/docs/advanced/security/index.md b/docs/zh/docs/advanced/security/index.md
index fdc8075c7..e2bef4765 100644
--- a/docs/zh/docs/advanced/security/index.md
+++ b/docs/zh/docs/advanced/security/index.md
@@ -2,7 +2,7 @@
## 附加特性
-除 [教程 - 用户指南: 安全性](../../tutorial/security/){.internal-link target=_blank} 中涵盖的功能之外,还有一些额外的功能来处理安全性.
+除 [教程 - 用户指南: 安全性](../../tutorial/security/index.md){.internal-link target=_blank} 中涵盖的功能之外,还有一些额外的功能来处理安全性.
!!! tip "小贴士"
接下来的章节 **并不一定是 "高级的"**.
@@ -11,6 +11,6 @@
## 先阅读教程
-接下来的部分假设你已经阅读了主要的 [教程 - 用户指南: 安全性](../../tutorial/security/){.internal-link target=_blank}.
+接下来的部分假设你已经阅读了主要的 [教程 - 用户指南: 安全性](../../tutorial/security/index.md){.internal-link target=_blank}.
它们都基于相同的概念,但支持一些额外的功能.
diff --git a/docs/zh/docs/advanced/security/oauth2-scopes.md b/docs/zh/docs/advanced/security/oauth2-scopes.md
new file mode 100644
index 000000000..e5eeffb0a
--- /dev/null
+++ b/docs/zh/docs/advanced/security/oauth2-scopes.md
@@ -0,0 +1,276 @@
+# OAuth2 作用域
+
+**FastAPI** 无缝集成 OAuth2 作用域(`Scopes`),可以直接使用。
+
+作用域是更精密的权限系统,遵循 OAuth2 标准,与 OpenAPI 应用(和 API 自动文档)集成。
+
+OAuth2 也是脸书、谷歌、GitHub、微软、推特等第三方身份验证应用使用的机制。这些身份验证应用在用户登录应用时使用 OAuth2 提供指定权限。
+
+脸书、谷歌、GitHub、微软、推特就是 OAuth2 作用域登录。
+
+本章介绍如何在 **FastAPI** 应用中使用 OAuth2 作用域管理验证与授权。
+
+!!! warning "警告"
+
+ 本章内容较难,刚接触 FastAPI 的新手可以跳过。
+
+ OAuth2 作用域不是必需的,没有它,您也可以处理身份验证与授权。
+
+ 但 OAuth2 作用域与 API(通过 OpenAPI)及 API 文档集成地更好。
+
+ 不管怎么说,**FastAPI** 支持在代码中使用作用域或其它安全/授权需求项。
+
+ 很多情况下,OAuth2 作用域就像一把牛刀。
+
+ 但如果您确定要使用作用域,或对它有兴趣,请继续阅读。
+
+## OAuth2 作用域与 OpenAPI
+
+OAuth2 规范的**作用域**是由空格分割的字符串组成的列表。
+
+这些字符串支持任何格式,但不能包含空格。
+
+作用域表示的是**权限**。
+
+OpenAPI 中(例如 API 文档)可以定义**安全方案**。
+
+这些安全方案在使用 OAuth2 时,还可以声明和使用作用域。
+
+**作用域**只是(不带空格的)字符串。
+
+常用于声明特定安全权限,例如:
+
+* 常见用例为,`users:read` 或 `users:write`
+* 脸书和 Instagram 使用 `instagram_basic`
+* 谷歌使用 `https://www.googleapis.com/auth/drive`
+
+!!! info "说明"
+
+ OAuth2 中,**作用域**只是声明特定权限的字符串。
+
+ 是否使用冒号 `:` 等符号,或是不是 URL 并不重要。
+
+ 这些细节只是特定的实现方式。
+
+ 对 OAuth2 来说,它们都只是字符串而已。
+
+## 全局纵览
+
+首先,快速浏览一下以下代码与**用户指南**中 [OAuth2 实现密码哈希与 Bearer JWT 令牌验证](../../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 安全方案
+
+第一个修改的地方是,使用两个作用域 `me` 和 `items ` 声明 OAuth2 安全方案。
+
+`scopes` 参数接收**字典**,键是作用域、值是作用域的描述:
+
+```Python hl_lines="62-65"
+{!../../../docs_src/security/tutorial005.py!}
+```
+
+因为声明了作用域,所以登录或授权时会在 API 文档中显示。
+
+此处,选择给予访问权限的作用域: `me` 和 `items`。
+
+这也是使用脸书、谷歌、GitHub 登录时的授权机制。
+
+

+
+## JWT 令牌作用域
+
+现在,修改令牌*路径操作*,返回请求的作用域。
+
+此处仍然使用 `OAuth2PasswordRequestForm`。它包含类型为**字符串列表**的 `scopes` 属性,且`scopes` 属性中包含要在请求里接收的每个作用域。
+
+这样,返回的 JWT 令牌中就包含了作用域。
+
+!!! danger "危险"
+
+ 为了简明起见,本例把接收的作用域直接添加到了令牌里。
+
+ 但在您的应用中,为了安全,应该只把作用域添加到确实需要作用域的用户,或预定义的用户。
+
+```Python hl_lines="153"
+{!../../../docs_src/security/tutorial005.py!}
+```
+
+## 在*路径操作*与依赖项中声明作用域
+
+接下来,为*路径操作* `/users/me/items/` 声明作用域 `items`。
+
+为此,要从 `fastapi` 中导入并使用 `Security` 。
+
+`Security` 声明依赖项的方式和 `Depends` 一样,但 `Security` 还能接收作用域(字符串)列表类型的参数 `scopes`。
+
+此处使用与 `Depends` 相同的方式,把依赖项函数 `get_current_active_user` 传递给 `Security`。
+
+同时,还传递了作用域**列表**,本例中只传递了一个作用域:`items`(此处支持传递更多作用域)。
+
+依赖项函数 `get_current_active_user` 还能声明子依赖项,不仅可以使用 `Depends`,也可以使用 `Security`。声明子依赖项函数(`get_current_user`)及更多作用域。
+
+本例要求使用作用域 `me`(还可以使用更多作用域)。
+
+!!! note "笔记"
+
+ 不必在不同位置添加不同的作用域。
+
+ 本例使用的这种方式只是为了展示 **FastAPI** 如何处理在不同层级声明的作用域。
+
+```Python hl_lines="4 139 166"
+{!../../../docs_src/security/tutorial005.py!}
+```
+
+!!! info "技术细节"
+
+ `Security` 实际上是 `Depends` 的子类,而且只比 `Depends` 多一个参数。
+
+ 但使用 `Security` 代替 `Depends`,**FastAPI** 可以声明安全作用域,并在内部使用这些作用域,同时,使用 OpenAPI 存档 API。
+
+ 但实际上,从 `fastapi` 导入的 `Query`、`Path`、`Depends`、`Security` 等对象,只是返回特殊类的函数。
+
+## 使用 `SecurityScopes`
+
+修改依赖项 `get_current_user`。
+
+这是上面的依赖项使用的依赖项。
+
+这里使用的也是之前创建的 OAuth2 方案,并把它声明为依赖项:`oauth2_scheme`。
+
+该依赖项函数本身不需要作用域,因此,可以使用 `Depends` 和 `oauth2_scheme`。不需要指定安全作用域时,不必使用 `Security`。
+
+此处还声明了从 `fastapin.security` 导入的 `SecurityScopes` 类型的特殊参数。
+
+`SecuriScopes` 类与 `Request` 类似(`Request` 用于直接提取请求对象)。
+
+```Python hl_lines="8 105"
+{!../../../docs_src/security/tutorial005.py!}
+```
+
+## 使用 `scopes`
+
+参数 `security_scopes` 的类型是 `SecurityScopes`。
+
+它的属性 `scopes` 是作用域列表,所有依赖项都把它作为子依赖项。也就是说所有**依赖**……这听起来有些绕,后文会有解释。
+
+(类 `SecurityScopes` 的)`security_scopes` 对象还提供了单字符串类型的属性 `scope_str`,该属性是(要在本例中使用的)用空格分割的作用域。
+
+此处还创建了后续代码中要复用(`raise`)的 `HTTPException` 。
+
+该异常包含了作用域所需的(如有),以空格分割的字符串(使用 `scope_str`)。该字符串要放到包含作用域的 `WWW-Authenticate` 请求头中(这也是规范的要求)。
+
+```Python hl_lines="105 107-115"
+{!../../../docs_src/security/tutorial005.py!}
+```
+
+## 校验 `username` 与数据形状
+
+我们可以校验是否获取了 `username`,并抽取作用域。
+
+然后,使用 Pydantic 模型校验数据(捕获 `ValidationError` 异常),如果读取 JWT 令牌或使用 Pydantic 模型验证数据时出错,就会触发之前创建的 `HTTPException` 异常。
+
+对此,要使用新的属性 `scopes` 更新 Pydantic 模型 `TokenData`。
+
+使用 Pydantic 验证数据可以确保数据中含有由作用域组成的**字符串列表**,以及 `username` 字符串等内容。
+
+反之,如果使用**字典**或其它数据结构,就有可能在后面某些位置破坏应用,形成安全隐患。
+
+还可以使用用户名验证用户,如果没有用户,也会触发之前创建的异常。
+
+```Python hl_lines="46 116-127"
+{!../../../docs_src/security/tutorial005.py!}
+```
+
+## 校验 `scopes`
+
+接下来,校验所有依赖项和依赖要素(包括*路径操作*)所需的作用域。这些作用域包含在令牌的 `scopes` 里,如果不在其中就会触发 `HTTPException` 异常。
+
+为此,要使用包含所有作用域**字符串列表**的 `security_scopes.scopes`, 。
+
+```Python hl_lines="128-134"
+{!../../../docs_src/security/tutorial005.py!}
+```
+
+## 依赖项树与作用域
+
+再次查看这个依赖项树与作用域。
+
+`get_current_active_user` 依赖项包含子依赖项 `get_current_user`,并在 `get_current_active_user`中声明了作用域 `"me"` 包含所需作用域列表 ,在 `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` 是包含上述声明的所有作用域的**列表**,因此:
+ * `security_scopes.scopes` 包含用于*路径操作*的 `["me", "items"]`
+ * `security_scopes.scopes` 包含*路径操作* `read_users_me` 的 `["me"]`,因为它在依赖项里被声明
+ * `security_scopes.scopes` 包含用于*路径操作* `read_system_status` 的 `[]`(空列表),并且它的依赖项 `get_current_user` 也没有声明任何 `scope`
+
+!!! tip "提示"
+
+ 此处重要且**神奇**的事情是,`get_current_user` 检查每个*路径操作*时可以使用不同的 `scopes` 列表。
+
+ 所有这些都依赖于在每个*路径操作*和指定*路径操作*的依赖树中的每个依赖项。
+
+## `SecurityScopes` 的更多细节
+
+您可以任何位置或多个位置使用 `SecurityScopes`,不一定非得在**根**依赖项中使用。
+
+它总是在当前 `Security` 依赖项中和所有依赖因子对于**特定** *路径操作*和**特定**依赖树中安全作用域
+
+因为 `SecurityScopes` 包含所有由依赖项声明的作用域,可以在核心依赖函数中用它验证所需作用域的令牌,然后再在不同的*路径操作*中声明不同作用域需求。
+
+它们会为每个*路径操作*进行单独检查。
+
+## 查看文档
+
+打开 API 文档,进行身份验证,并指定要授权的作用域。
+
+

+
+没有选择任何作用域,也可以进行**身份验证**,但访问 `/uses/me` 或 `/users/me/items` 时,会显示没有足够的权限。但仍可以访问 `/status/`。
+
+如果选择了作用域 `me`,但没有选择作用域 `items`,则可以访问 `/users/me/`,但不能访问 `/users/me/items`。
+
+这就是通过用户提供的令牌使用第三方应用访问这些*路径操作*时会发生的情况,具体怎样取决于用户授予第三方应用的权限。
+
+## 关于第三方集成
+
+本例使用 OAuth2 **密码**流。
+
+这种方式适用于登录我们自己的应用,最好使用我们自己的前端。
+
+因为我们能控制自己的前端应用,可以信任它接收 `username` 与 `password`。
+
+但如果构建的是连接其它应用的 OAuth2 应用,比如具有与脸书、谷歌、GitHub 相同功能的第三方身份验证应用。那您就应该使用其它安全流。
+
+最常用的是隐式流。
+
+最安全的是代码流,但实现起来更复杂,而且需要更多步骤。因为它更复杂,很多第三方身份验证应用最终建议使用隐式流。
+
+!!! note "笔记"
+
+ 每个身份验证应用都会采用不同方式会命名流,以便融合入自己的品牌。
+
+ 但归根结底,它们使用的都是 OAuth2 标准。
+
+**FastAPI** 的 `fastapi.security.oauth2` 里包含了所有 OAuth2 身份验证流工具。
+
+## 装饰器 `dependencies` 中的 `Security`
+
+同样,您可以在装饰器的 `dependencies` 参数中定义 `Depends` 列表,(详见[路径操作装饰器依赖项](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank})),也可以把 `scopes` 与 `Security` 一起使用。
diff --git a/docs/zh/docs/advanced/settings.md b/docs/zh/docs/advanced/settings.md
index 76070fb7f..d793b9c7f 100644
--- a/docs/zh/docs/advanced/settings.md
+++ b/docs/zh/docs/advanced/settings.md
@@ -127,7 +127,7 @@ Hello World from Python
## Pydantic 的 `Settings`
-幸运的是,Pydantic 提供了一个很好的工具来处理来自环境变量的设置,即
Pydantic: Settings management。
+幸运的是,Pydantic 提供了一个很好的工具来处理来自环境变量的设置,即
Pydantic: Settings management。
### 创建 `Settings` 对象
@@ -314,7 +314,7 @@ APP_NAME="ChimichangApp"
在这里,我们在 Pydantic 的 `Settings` 类中创建了一个名为 `Config` 的类,并将 `env_file` 设置为我们想要使用的 dotenv 文件的文件名。
!!! tip
- `Config` 类仅用于 Pydantic 配置。您可以在
Pydantic Model Config中阅读更多相关信息。
+ `Config` 类仅用于 Pydantic 配置。您可以在
Pydantic Model Config中阅读更多相关信息。
### 使用 `lru_cache` 仅创建一次 `Settings`
diff --git a/docs/zh/docs/advanced/sub-applications.md b/docs/zh/docs/advanced/sub-applications.md
new file mode 100644
index 000000000..55651def5
--- /dev/null
+++ b/docs/zh/docs/advanced/sub-applications.md
@@ -0,0 +1,73 @@
+# 子应用 - 挂载
+
+如果需要两个独立的 FastAPI 应用,拥有各自独立的 OpenAPI 与文档,则需设置一个主应用,并**挂载**一个(或多个)子应用。
+
+## 挂载 **FastAPI** 应用
+
+**挂载**是指在特定路径中添加完全**独立**的应用,然后在该路径下使用*路径操作*声明的子应用处理所有事务。
+
+### 顶层应用
+
+首先,创建主(顶层)**FastAPI** 应用及其*路径操作*:
+
+```Python hl_lines="3 6-8"
+{!../../../docs_src/sub_applications/tutorial001.py!}
+```
+
+### 子应用
+
+接下来,创建子应用及其*路径操作*。
+
+子应用只是另一个标准 FastAPI 应用,但这个应用是被**挂载**的应用:
+
+```Python hl_lines="11 14-16"
+{!../../../docs_src/sub_applications/tutorial001.py!}
+```
+
+### 挂载子应用
+
+在顶层应用 `app` 中,挂载子应用 `subapi`。
+
+本例的子应用挂载在 `/subapi` 路径下:
+
+```Python hl_lines="11 19"
+{!../../../docs_src/sub_applications/tutorial001.py!}
+```
+
+### 查看文档
+
+如果主文件是 `main.py`,则用以下 `uvicorn` 命令运行主应用:
+
+
+
+```console
+$ uvicorn main:app --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+
+
+查看文档
http://127.0.0.1:8000/docs。
+
+下图显示的是主应用 API 文档,只包括其自有的*路径操作*。
+
+

+
+然后查看子应用文档
http://127.0.0.1:8000/subapi/docs。
+
+下图显示的是子应用的 API 文档,也是只包括其自有的*路径操作*,所有这些路径操作都在 `/subapi` 子路径前缀下。
+
+

+
+两个用户界面都可以正常运行,因为浏览器能够与每个指定的应用或子应用会话。
+
+### 技术细节:`root_path`
+
+以上述方式挂载子应用时,FastAPI 使用 ASGI 规范中的 `root_path` 机制处理挂载子应用路径之间的通信。
+
+这样,子应用就可以为自动文档使用路径前缀。
+
+并且子应用还可以再挂载子应用,一切都会正常运行,FastAPI 可以自动处理所有 `root_path`。
+
+关于 `root_path` 及如何显式使用 `root_path` 的内容,详见[使用代理](./behind-a-proxy.md){.internal-link target=_blank}一章。
diff --git a/docs/zh/docs/advanced/templates.md b/docs/zh/docs/advanced/templates.md
new file mode 100644
index 000000000..d735f1697
--- /dev/null
+++ b/docs/zh/docs/advanced/templates.md
@@ -0,0 +1,94 @@
+# 模板
+
+**FastAPI** 支持多种模板引擎。
+
+Flask 等工具使用的 Jinja2 是最用的模板引擎。
+
+在 Starlette 的支持下,**FastAPI** 应用可以直接使用工具轻易地配置 Jinja2。
+
+## 安装依赖项
+
+安装 `jinja2`:
+
+
+
+```console
+$ pip install jinja2
+
+---> 100%
+```
+
+
+
+如需使用静态文件,还要安装 `aiofiles`:
+
+
+
+```console
+$ pip install aiofiles
+
+---> 100%
+```
+
+
+
+## 使用 `Jinja2Templates`
+
+* 导入 `Jinja2Templates`
+* 创建可复用的 `templates` 对象
+* 在返回模板的*路径操作*中声明 `Request` 参数
+* 使用 `templates` 渲染并返回 `TemplateResponse`, 以键值对方式在 Jinja2 的 **context** 中传递 `request`
+
+```Python hl_lines="4 11 15-16"
+{!../../../docs_src/templates/tutorial001.py!}
+```
+
+!!! note "笔记"
+
+ 注意,必须为 Jinja2 以键值对方式在上下文中传递 `request`。因此,还要在*路径操作*中声明。
+
+!!! tip "提示"
+
+ 通过声明 `response_class=HTMLResponse`,API 文档就能识别响应的对象是 HTML。
+
+!!! note "技术细节"
+
+ 您还可以使用 `from starlette.templating import Jinja2Templates`。
+
+ **FastAPI** 的 `fastapi.templating` 只是为开发者提供的快捷方式。实际上,绝大多数可用响应都直接继承自 Starlette。 `Request` 与 `StaticFiles` 也一样。
+
+## 编写模板
+
+编写模板 `templates/item.html`,代码如下:
+
+```jinja hl_lines="7"
+{!../../../docs_src/templates/templates/item.html!}
+```
+
+它会显示从 **context** 字典中提取的 `id`:
+
+```Python
+{"request": request, "id": id}
+```
+
+## 模板与静态文件
+
+在模板内部使用 `url_for()`,例如,与挂载的 `StaticFiles` 一起使用。
+
+```jinja hl_lines="4"
+{!../../../docs_src/templates/templates/item.html!}
+```
+
+本例中,使用 `url_for()` 为模板添加 CSS 文件 `static/styles.css` 链接:
+
+```CSS hl_lines="4"
+{!../../../docs_src/templates/static/styles.css!}
+```
+
+因为使用了 `StaticFiles`, **FastAPI** 应用自动提供位于 URL `/static/styles.css`
+
+的 CSS 文件。
+
+## 更多说明
+
+包括测试模板等更多详情,请参阅
Starlette 官档 - 模板。
diff --git a/docs/zh/docs/advanced/testing-dependencies.md b/docs/zh/docs/advanced/testing-dependencies.md
new file mode 100644
index 000000000..dc0f88b33
--- /dev/null
+++ b/docs/zh/docs/advanced/testing-dependencies.md
@@ -0,0 +1,51 @@
+# 测试依赖项
+
+## 测试时覆盖依赖项
+
+有些场景下,您可能需要在测试时覆盖依赖项。
+
+即不希望运行原有依赖项(及其子依赖项)。
+
+反之,要在测试期间(或只是为某些特定测试)提供只用于测试的依赖项,并使用此依赖项的值替换原有依赖项的值。
+
+### 用例:外部服务
+
+常见实例是调用外部第三方身份验证应用。
+
+向第三方应用发送令牌,然后返回经验证的用户。
+
+但第三方服务商处理每次请求都可能会收费,并且耗时通常也比调用写死的模拟测试用户更长。
+
+一般只要测试一次外部验证应用就够了,不必每次测试都去调用。
+
+此时,最好覆盖调用外部验证应用的依赖项,使用返回模拟测试用户的自定义依赖项就可以了。
+
+### 使用 `app.dependency_overrides` 属性
+
+对于这些用例,**FastAPI** 应用支持 `app.dependcy_overrides` 属性,该属性就是**字典**。
+
+要在测试时覆盖原有依赖项,这个字典的键应当是原依赖项(函数),值是覆盖依赖项(另一个函数)。
+
+这样一来,**FastAPI** 就会调用覆盖依赖项,不再调用原依赖项。
+
+```Python hl_lines="26-27 30"
+{!../../../docs_src/dependency_testing/tutorial001.py!}
+```
+
+!!! tip "提示"
+
+ **FastAPI** 应用中的任何位置都可以实现覆盖依赖项。
+
+ 原依赖项可用于*路径操作函数*、*路径操作装饰器*(不需要返回值时)、`.include_router()` 调用等。
+
+ FastAPI 可以覆盖这些位置的依赖项。
+
+然后,使用 `app.dependency_overrides` 把覆盖依赖项重置为空**字典**:
+
+```Python
+app.dependency_overrides = {}
+```
+
+!!! tip "提示"
+
+ 如果只在某些测试时覆盖依赖项,您可以在测试开始时(在测试函数内)设置覆盖依赖项,并在结束时(在测试函数结尾)重置覆盖依赖项。
diff --git a/docs/zh/docs/advanced/using-request-directly.md b/docs/zh/docs/advanced/using-request-directly.md
new file mode 100644
index 000000000..1842c2e27
--- /dev/null
+++ b/docs/zh/docs/advanced/using-request-directly.md
@@ -0,0 +1,54 @@
+# 直接使用请求
+
+至此,我们已经使用多种类型声明了请求的各种组件。
+
+并从以下对象中提取数据:
+
+* 路径参数
+* 请求头
+* Cookies
+* 等
+
+**FastAPI** 使用这种方式验证数据、转换数据,并自动生成 API 文档。
+
+但有时,我们也需要直接访问 `Request` 对象。
+
+## `Request` 对象的细节
+
+实际上,**FastAPI** 的底层是 **Starlette**,**FastAPI** 只不过是在 **Starlette** 顶层提供了一些工具,所以能直接使用 Starlette 的
`Request` 对象。
+
+但直接从 `Request` 对象提取数据时(例如,读取请求体),**FastAPI** 不会验证、转换和存档数据(为 API 文档使用 OpenAPI)。
+
+不过,仍可以验证、转换与注释(使用 Pydantic 模型的请求体等)其它正常声明的参数。
+
+但在某些特定情况下,还是需要提取 `Request` 对象。
+
+## 直接使用 `Request` 对象
+
+假设要在*路径操作函数*中获取客户端 IP 地址和主机。
+
+此时,需要直接访问请求。
+
+```Python hl_lines="1 7-8"
+{!../../../docs_src/using_request_directly/tutorial001.py!}
+```
+
+把*路径操作函数*的参数类型声明为 `Request`,**FastAPI** 就能把 `Request` 传递到参数里。
+
+!!! tip "提示"
+
+ 注意,本例除了声明请求参数之外,还声明了路径参数。
+
+ 因此,能够提取、验证路径参数、并转换为指定类型,还可以用 OpenAPI 注释。
+
+ 同样,您也可以正常声明其它参数,而且还可以提取 `Request`。
+
+## `Request` 文档
+
+更多细节详见
Starlette 官档 - `Request` 对象。
+
+!!! note "技术细节"
+
+ 您也可以使用 `from starlette.requests import Request`。
+
+ **FastAPI** 的 `from fastapi import Request` 只是为开发者提供的快捷方式,但其实它直接继承自 Starlette。
diff --git a/docs/zh/docs/async.md b/docs/zh/docs/async.md
index 59eebd049..ed0e6e497 100644
--- a/docs/zh/docs/async.md
+++ b/docs/zh/docs/async.md
@@ -405,7 +405,7 @@ Starlette (和 **FastAPI**) 是基于
I/O 的代码。
-在这两种情况下,与您之前的框架相比,**FastAPI** 可能[仍然很快](/#performance){.internal-link target=_blank}。
+在这两种情况下,与您之前的框架相比,**FastAPI** 可能[仍然很快](index.md#performance){.internal-link target=_blank}。
### 依赖
diff --git a/docs/zh/docs/contributing.md b/docs/zh/docs/contributing.md
index 4ebd67315..3dfc3db7c 100644
--- a/docs/zh/docs/contributing.md
+++ b/docs/zh/docs/contributing.md
@@ -1,6 +1,6 @@
# 开发 - 贡献
-首先,你最好先了解 [帮助 FastAPI 及获取帮助](help-fastapi.md){.internal-link target=_blank}的基本方式。
+首先,你可能想了解 [帮助 FastAPI 及获取帮助](help-fastapi.md){.internal-link target=_blank}的基本方式。
## 开发
@@ -84,6 +84,17 @@ $ python -m venv env
如果显示 `pip` 程序文件位于 `env/bin/pip` 则说明激活成功。 🎉
+确保虚拟环境中的 pip 版本是最新的,以避免后续步骤出现错误:
+
+
+
+```console
+$ python -m pip install --upgrade pip
+
+---> 100%
+```
+
+
!!! tip
每一次你在该环境下使用 `pip` 安装了新软件包时,请再次激活该环境。
@@ -114,6 +125,11 @@ $ pip install -r requirements.txt
这样,你不必再去重新"安装"你的本地版本即可测试所有更改。
+!!! note "技术细节"
+ 仅当你使用此项目中的 `requirements.txt` 安装而不是直接使用 `pip install fastapi` 安装时,才会发生这种情况。
+
+ 这是因为在 `requirements.txt` 中,本地的 FastAPI 是使用“可编辑” (`-e`)选项安装的
+
### 格式化
你可以运行下面的脚本来格式化和清理所有代码:
@@ -126,91 +142,93 @@ $ bash scripts/format.sh
-它还会自动对所有导入代码进行整理。
+它还会自动对所有导入代码进行排序整理。
为了使整理正确进行,你需要在当前环境中安装本地的 FastAPI,即在运行上述段落中的命令时添加 `-e`。
-### 格式化导入
+## 文档
+
+首先,请确保按上述步骤设置好环境,这将安装所有需要的依赖。
-还有另一个脚本可以格式化所有导入,并确保你没有未使用的导入代码:
+### 实时文档
+
+在本地开发时,可以使用该脚本构建站点并检查所做的任何更改,并实时重载:
```console
-$ bash scripts/format-imports.sh
+$ python ./scripts/docs.py live
+
+[INFO] Serving on http://127.0.0.1:8008
+[INFO] Start watching changes
+[INFO] Start detecting changes
```
-由于它依次运行了多个命令,并修改和还原了许多文件,所以运行时间会更长一些,因此经常地使用 `scripts/format.sh` 然后仅在提交前执行 `scripts/format-imports.sh` 会更好一些。
+文档服务将运行在 `http://127.0.0.1:8008`。
-## 文档
-
-首先,请确保按上述步骤设置好环境,这将安装所有需要的依赖。
-
-文档使用
MkDocs 生成。
-
-并且在 `./scripts/docs.py` 中还有适用的额外工具/脚本来处理翻译。
+这样,你可以编辑文档 / 源文件并实时查看更改。
!!! tip
- 你不需要去了解 `./scripts/docs.py` 中的代码,只需在命令行中使用它即可。
+ 或者你也可以手动执行和该脚本一样的操作
-所有文档均在 `./docs/en/` 目录中以 Markdown 文件格式保存。
-
-许多的教程章节里包含有代码块。
+ 进入语言目录,如果是英文文档,目录则是 `docs/en/`:
-在大多数情况下,这些代码块是可以直接运行的真实完整的应用程序。
-
-实际上,这些代码块不是写在 Markdown 文件内的,它们是位于 `./docs_src/` 目录中的 Python 文件。
+ ```console
+ $ cd docs/en/
+ ```
-生成站点时,这些 Python 文件会被包含/注入到文档中。
+ 在该目录执行 `mkdocs` 命令
-### 用于测试的文档
+ ```console
+ $ mkdocs serve --dev-addr 8008
+ ```
-大多数的测试实际上都是针对文档中的示例源文件运行的。
+#### Typer CLI (可选)
-这有助于确保:
+本指引向你展示了如何直接用 `python` 运行 `./scripts/docs.py` 中的脚本。
-* 文档始终是最新的。
-* 文档示例可以直接运行。
-* 绝大多数特性既在文档中得以阐述,又通过测试覆盖进行保障。
+但你也可以使用
Typer CLI,而且在安装了补全功能后,你将可以在终端中对命令进行自动补全。
-在本地开发期间,有一个脚本可以实时重载地构建站点并用来检查所做的任何更改:
+如果你已经安装 Typer CLI ,则可以使用以下命令安装自动补全功能:
```console
-$ python ./scripts/docs.py live
+$ typer --install-completion
-[INFO] Serving on http://127.0.0.1:8008
-[INFO] Start watching changes
-[INFO] Start detecting changes
+zsh completion installed in /home/user/.bashrc.
+Completion will take effect once you restart the terminal.
```
-它将在 `http://127.0.0.1:8008` 提供对文档的访问。
+### 文档架构
-这样,你可以编辑文档/源文件并实时查看更改。
+文档使用
MkDocs 生成。
-#### Typer CLI (可选)
+在 `./scripts/docs.py` 中还有额外工具 / 脚本来处理翻译。
-本指引向你展示了如何直接用 `python` 程序运行 `./scripts/docs.py` 中的脚本。
+!!! tip
+ 你不需要去了解 `./scripts/docs.py` 中的代码,只需在命令行中使用它即可。
-但你也可以使用
Typer CLI,而且在安装了补全功能后,你将可以在终端中对命令进行自动补全。
+所有文档均在 `./docs/en/` 目录中以 Markdown 文件格式保存。
-如果你打算安装 Typer CLI ,可以使用以下命令安装自动补全功能:
+许多的教程中都有一些代码块,大多数情况下,这些代码是可以直接运行的,因为这些代码不是写在 Markdown 文件里的,而是写在 `./docs_src/` 目录中的 Python 文件里。
-
+在生成站点的时候,这些 Python 文件会被打包进文档中。
-```console
-$ typer --install-completion
+### 测试文档
-zsh completion installed in /home/user/.bashrc.
-Completion will take effect once you restart the terminal.
-```
+大多数的测试实际上都是针对文档中的示例源文件运行的。
+
+这有助于确保:
+
+* 文档始终是最新的。
+* 文档示例可以直接运行。
+* 绝大多数特性既在文档中得以阐述,又通过测试覆盖进行保障。
-
### 应用和文档同时运行
@@ -230,7 +248,7 @@ $ uvicorn tutorial001:app --reload
### 翻译
-非常感谢你能够参与文档的翻译!这项工作需要社区的帮助才能完成。 🌎 🚀
+**非常感谢**你能够参与文档的翻译!这项工作需要社区的帮助才能完成。 🌎 🚀
以下是参与帮助翻译的步骤。
@@ -243,17 +261,19 @@ $ uvicorn tutorial001:app --reload
详情可查看关于
添加 pull request 评审意见 以同意合并或要求修改的文档。
-* 在
issues 中查找是否有对你所用语言所进行的协作翻译。
+* 检查在
GitHub Discussion 是否有关于你所用语言的协作翻译。 如果有,你可以订阅它,当有一条新的 PR 请求需要评审时,系统会自动将其添加到讨论中,你也会收到对应的推送。
* 每翻译一个页面新增一个 pull request。这将使其他人更容易对其进行评审。
对于我(译注:作者使用西班牙语和英语)不懂的语言,我将在等待其他人评审翻译之后将其合并。
* 你还可以查看是否有你所用语言的翻译,并对其进行评审,这将帮助我了解翻译是否正确以及能否将其合并。
+ * 可以在
GitHub Discussions 中查看。
+ * 也可以在现有 PR 中通过你使用的语言标签来筛选对应的 PR,举个例子,对于西班牙语,标签是
`lang-es`。
-* 使用相同的 Python 示例并且仅翻译文档中的文本。无需进行任何其他更改示例也能正常工作。
+* 请使用相同的 Python 示例,且只需翻译文档中的文本,不用修改其它东西。
-* 使用相同的图片、文件名以及链接地址。无需进行任何其他调整来让它们兼容。
+* 请使用相同的图片、文件名以及链接地址,不用修改其它东西。
* 你可以从
ISO 639-1 代码列表 表中查找你想要翻译语言的两位字母代码。
@@ -264,7 +284,7 @@ $ uvicorn tutorial001:app --reload
对于西班牙语来说,它的两位字母代码是 `es`。所以西班牙语翻译的目录位于 `docs/es/`。
!!! tip
- 主要("官方")语言是英语,位于 `docs/en/`目录。
+ 默认语言是英语,位于 `docs/en/`目录。
现在为西班牙语文档运行实时服务器:
@@ -281,11 +301,24 @@ $ python ./scripts/docs.py live es
-现在你可以访问
http://127.0.0.1:8008 实时查看你所做的更改。
+!!! tip
+ 或者你也可以手动执行和该脚本一样的操作
-如果你查看 FastAPI 的线上文档网站,会看到每种语言都有所有页面。但是某些页面并未被翻译并且会有一处关于缺少翻译的提示。
+ 进入语言目录,对于西班牙语的翻译,目录是 `docs/es/`:
-但是当你像上面这样在本地运行文档时,你只会看到已经翻译的页面。
+ ```console
+ $ cd docs/es/
+ ```
+
+ 在该目录执行 `mkdocs` 命令
+
+ ```console
+ $ mkdocs serve --dev-addr 8008
+ ```
+
+现在你可以访问
http://127.0.0.1:8008 实时查看你所做的更改。
+
+如果你查看 FastAPI 的线上文档网站,会看到每种语言都有所有的文档页面,但是某些页面并未被翻译并且会有一处关于缺少翻译的提示。(但是当你像上面这样在本地运行文档时,你只会看到已经翻译的页面。)
现在假设你要为 [Features](features.md){.internal-link target=_blank} 章节添加翻译。
@@ -304,49 +337,9 @@ docs/es/docs/features.md
!!! tip
注意路径和文件名的唯一变化是语言代码,从 `en` 更改为 `es`。
-* 现在打开位于英语文档目录下的 MkDocs 配置文件:
+回到浏览器你就可以看到刚刚更新的章节了。🎉
-```
-docs/en/docs/mkdocs.yml
-```
-
-* 在配置文件中找到 `docs/features.md` 所在的位置。结果像这样:
-
-```YAML hl_lines="8"
-site_name: FastAPI
-# More stuff
-nav:
-- FastAPI: index.md
-- Languages:
- - en: /
- - es: /es/
-- features.md
-```
-
-* 打开你正在编辑的语言目录中的 MkDocs 配置文件,例如:
-
-```
-docs/es/docs/mkdocs.yml
-```
-
-* 将其添加到与英语文档完全相同的位置,例如:
-
-```YAML hl_lines="8"
-site_name: FastAPI
-# More stuff
-nav:
-- FastAPI: index.md
-- Languages:
- - en: /
- - es: /es/
-- features.md
-```
-
-如果配置文件中还有其他条目,请确保你所翻译的新条目和它们之间的顺序与英文版本完全相同。
-
-打开浏览器,现在你将看到文档展示了你所加入的新章节。 🎉
-
-现在,你可以将它全部翻译完并在保存文件后进行预览。
+现在,你可以翻译这些内容并在保存文件后进行预览。
#### 新语言
@@ -354,7 +347,7 @@ nav:
假设你想要添加克里奥尔语翻译,而且文档中还没有该语言的翻译。
-点击上面提到的链接,可以查到"克里奥尔语"的代码为 `ht`。
+点击上面提到的“ISO 639-1 代码列表”链接,可以查到“克里奥尔语”的代码为 `ht`。
下一步是运行脚本以生成新的翻译目录:
@@ -365,55 +358,32 @@ nav:
$ python ./scripts/docs.py new-lang ht
Successfully initialized: docs/ht
-Updating ht
-Updating en
```
现在,你可以在编辑器中查看新创建的目录 `docs/ht/`。
-!!! tip
- 在添加实际的翻译之前,仅以此创建首个 pull request 来设定新语言的配置。
-
- 这样当你在翻译第一个页面时,其他人可以帮助翻译其他页面。🚀
-
-首先翻译文档主页 `docs/ht/index.md`。
-
-然后,你可以根据上面的"已有语言"的指引继续进行翻译。
+这条命令会生成一个从 `en` 版本继承了所有属性的配置文件 `docs/ht/mkdocs.yml`:
-##### 不支持的新语言
-
-如果在运行实时服务器脚本时收到关于不支持该语言的错误,类似于:
-
-```
- raise TemplateNotFound(template)
-jinja2.exceptions.TemplateNotFound: partials/language/xx.html
+```yaml
+INHERIT: ../en/mkdocs.yml
```
-这意味着文档的主题不支持该语言(在这种例子中,编造的语言代码是 `xx`)。
-
-但是别担心,你可以将主题语言设置为英语,然后翻译文档的内容。
-
-如果你需要这么做,编辑新语言目录下的 `mkdocs.yml`,它将有类似下面的内容:
+!!! tip
+ 你也可以自己手动创建包含这些内容的文件。
-```YAML hl_lines="5"
-site_name: FastAPI
-# More stuff
-theme:
- # More stuff
- language: xx
-```
+这条命令还会生成一个文档主页 `docs/ht/index.md`,你可以从这个文件开始翻译。
-将其中的 language 项从 `xx`(你的语言代码)更改为 `en`。
+然后,你可以根据上面的"已有语言"的指引继续进行翻译。
-然后,你就可以再次启动实时服务器了。
+翻译完成后,你就可以用 `docs/ht/mkdocs.yml` 和 `docs/ht/index.md` 发起 PR 了。🎉
#### 预览结果
-当你通过 `live` 命令使用 `./scripts/docs.py` 中的脚本时,该脚本仅展示当前语言已有的文件和翻译。
+你可以执行 `./scripts/docs.py live` 命令来预览结果(或者 `mkdocs serve`)。
-但是当你完成翻译后,你可以像在线上展示一样测试所有内容。
+但是当你完成翻译后,你可以像在线上展示一样测试所有内容,包括所有其他语言。
为此,首先构建所有文档:
@@ -423,19 +393,16 @@ theme:
// Use the command "build-all", this will take a bit
$ python ./scripts/docs.py build-all
-Updating es
-Updating en
Building docs for: en
Building docs for: es
Successfully built docs for: es
-Copying en index.md to README.md
```
-这将在 `./docs_build/` 目录中为每一种语言生成全部的文档。还包括添加所有缺少翻译的文件,并带有一条"此文件还没有翻译"的提醒。但是你不需要对该目录执行任何操作。
+这样会对每一种语言构建一个独立的文档站点,并最终把这些站点全部打包输出到 `./site/` 目录。
+
-然后,它针对每种语言构建独立的 MkDocs 站点,将它们组合在一起,并在 `./site/` 目录中生成最终的输出。
然后你可以使用命令 `serve` 来运行生成的站点:
diff --git a/docs/zh/docs/deployment/deta.md b/docs/zh/docs/deployment/deta.md
deleted file mode 100644
index a7390f786..000000000
--- a/docs/zh/docs/deployment/deta.md
+++ /dev/null
@@ -1,244 +0,0 @@
-# 在 Deta 上部署 FastAPI
-
-本节介绍如何使用
Deta 免费方案部署 **FastAPI** 应用。🎁
-
-部署操作需要大约 10 分钟。
-
-!!! info "说明"
-
-
Deta 是 **FastAPI** 的赞助商。 🎉
-
-## 基础 **FastAPI** 应用
-
-* 创建应用文件夹,例如 `./fastapideta/`,进入文件夹
-
-### FastAPI 代码
-
-* 创建包含如下代码的 `main.py`:
-
-```Python
-from fastapi import FastAPI
-
-app = FastAPI()
-
-
-@app.get("/")
-def read_root():
- return {"Hello": "World"}
-
-
-@app.get("/items/{item_id}")
-def read_item(item_id: int):
- return {"item_id": item_id}
-```
-
-### 需求项
-
-在文件夹里新建包含如下内容的 `requirements.txt` 文件:
-
-```text
-fastapi
-```
-
-!!! tip "提示"
-
- 在 Deta 上部署时无需安装 Uvicorn,虽然在本地测试应用时需要安装。
-
-### 文件夹架构
-
-`./fastapideta/` 文件夹中现在有两个文件:
-
-```
-.
-└── main.py
-└── requirements.txt
-```
-
-## 创建免费 Deta 账号
-
-创建
免费的 Deta 账号,只需要电子邮件和密码。
-
-甚至不需要信用卡。
-
-## 安装 CLI
-
-创建账号后,安装 Deta
CLI:
-
-=== "Linux, macOS"
-
-
-
- ```console
- $ curl -fsSL https://get.deta.dev/cli.sh | sh
- ```
-
-
-
-=== "Windows PowerShell"
-
-
-
- ```console
- $ iwr https://get.deta.dev/cli.ps1 -useb | iex
- ```
-
-
-
-安装完 CLI 后,打开新的 Terminal,就能检测到刚安装的 CLI。
-
-在新的 Terminal 里,用以下命令确认 CLI 是否正确安装:
-
-
-
-```console
-$ deta --help
-
-Deta command line interface for managing deta micros.
-Complete documentation available at https://docs.deta.sh
-
-Usage:
- deta [flags]
- deta [command]
-
-Available Commands:
- auth Change auth settings for a deta micro
-
-...
-```
-
-
-
-!!! tip "提示"
-
- 安装 CLI 遇到问题时,请参阅
Deta 官档。
-
-## 使用 CLI 登录
-
-现在,使用 CLI 登录 Deta:
-
-
-
-```console
-$ deta login
-
-Please, log in from the web page. Waiting..
-Logged in successfully.
-```
-
-
-
-这个命令会打开浏览器并自动验证身份。
-
-## 使用 Deta 部署
-
-接下来,使用 Deta CLI 部署应用:
-
-
-
-```console
-$ deta new
-
-Successfully created a new micro
-
-// Notice the "endpoint" 🔍
-
-{
- "name": "fastapideta",
- "runtime": "python3.7",
- "endpoint": "https://qltnci.deta.dev",
- "visor": "enabled",
- "http_auth": "enabled"
-}
-
-Adding dependencies...
-
-
----> 100%
-
-
-Successfully installed fastapi-0.61.1 pydantic-1.7.2 starlette-0.13.6
-```
-
-
-
-您会看到如下 JSON 信息:
-
-```JSON hl_lines="4"
-{
- "name": "fastapideta",
- "runtime": "python3.7",
- "endpoint": "https://qltnci.deta.dev",
- "visor": "enabled",
- "http_auth": "enabled"
-}
-```
-
-!!! tip "提示"
-
- 您部署时的 `"endpoint"` URL 可能会有所不同。
-
-## 查看效果
-
-打开浏览器,跳转到 `endpoint` URL。本例中是 `https://qltnci.deta.dev`,但您的链接可能与此不同。
-
-FastAPI 应用会返回如下 JSON 响应:
-
-```JSON
-{
- "Hello": "World"
-}
-```
-
-接下来,跳转到 API 文档 `/docs`,本例中是 `https://qltnci.deta.dev/docs`。
-
-文档显示如下:
-
-

-
-## 启用公开访问
-
-默认情况下,Deta 使用您的账号 Cookies 处理身份验证。
-
-应用一切就绪之后,使用如下命令让公众也能看到您的应用:
-
-
-
-```console
-$ deta auth disable
-
-Successfully disabled http auth
-```
-
-
-
-现在,就可以把 URL 分享给大家,他们就能访问您的 API 了。🚀
-
-## HTTPS
-
-恭喜!您已经在 Deta 上部署了 FastAPI 应用!🎉 🍰
-
-还要注意,Deta 能够正确处理 HTTPS,因此您不必操心 HTTPS,您的客户端肯定能有安全加密的连接。 ✅ 🔒
-
-## 查看 Visor
-
-从 API 文档(URL 是 `https://gltnci.deta.dev/docs`)发送请求至*路径操作* `/items/{item_id}`。
-
-例如,ID `5`。
-
-现在跳转至
https://web.deta.sh。
-
-左边栏有个
"Micros" 标签,里面是所有的应用。
-
-还有一个 **Details** 和 **Visor** 标签,跳转到 **Visor** 标签。
-
-在这里查看最近发送给应用的请求。
-
-您可以编辑或重新使用这些请求。
-
-

-
-## 更多内容
-
-如果要持久化保存应用数据,可以使用提供了**免费方案**的
Deta Base。
-
-详见
Deta 官档。
diff --git a/docs/zh/docs/fastapi-people.md b/docs/zh/docs/fastapi-people.md
index 5d7b0923f..7ef3f3c1a 100644
--- a/docs/zh/docs/fastapi-people.md
+++ b/docs/zh/docs/fastapi-people.md
@@ -40,7 +40,7 @@ FastAPI 有一个非常棒的社区,它欢迎来自各个领域和背景的朋
{% if people %}
-{% for user in people.last_month_active %}
+{% for user in people.last_month_experts[:10] %}
{% endfor %}
@@ -58,7 +58,7 @@ FastAPI 有一个非常棒的社区,它欢迎来自各个领域和背景的朋
{% if people %}
-{% for user in people.experts %}
+{% for user in people.experts[:50] %}
{% endfor %}
@@ -76,7 +76,7 @@ FastAPI 有一个非常棒的社区,它欢迎来自各个领域和背景的朋
{% if people %}
-{% for user in people.top_contributors %}
+{% for user in people.top_contributors[:50] %}
{% endfor %}
@@ -100,7 +100,7 @@ FastAPI 有一个非常棒的社区,它欢迎来自各个领域和背景的朋
{% if people %}
-{% for user in people.top_reviewers %}
+{% for user in people.top_translations_reviewers[:50] %}
{% endfor %}
diff --git a/docs/zh/docs/features.md b/docs/zh/docs/features.md
index 2db7f852a..d8190032f 100644
--- a/docs/zh/docs/features.md
+++ b/docs/zh/docs/features.md
@@ -179,7 +179,7 @@ FastAPI 有一个使用非常简单,但是非常强大的
IDE/
linter/brain** 适配:
* 因为 pydantic 数据结构仅仅是你定义的类的实例;自动补全,linting,mypy 以及你的直觉应该可以和你验证的数据一起正常工作。
-* **更快**:
- * 在
基准测试 中,Pydantic 比其他被测试的库都要快。
* 验证**复杂结构**:
* 使用分层的 Pydantic 模型, Python `typing`的 `List` 和 `Dict` 等等。
* 验证器使我们能够简单清楚的将复杂的数据模式定义、检查并记录为 JSON Schema。
diff --git a/docs/zh/docs/help-fastapi.md b/docs/zh/docs/help-fastapi.md
index 9b70d115a..1a9aa57d0 100644
--- a/docs/zh/docs/help-fastapi.md
+++ b/docs/zh/docs/help-fastapi.md
@@ -12,7 +12,7 @@
## 订阅新闻邮件
-您可以订阅 [**FastAPI 和它的小伙伴** 新闻邮件](/newsletter/){.internal-link target=_blank}(不会经常收到)
+您可以订阅 [**FastAPI 和它的小伙伴** 新闻邮件](newsletter.md){.internal-link target=_blank}(不会经常收到)
* FastAPI 及其小伙伴的新闻 🚀
* 指南 📝
diff --git a/docs/zh/docs/history-design-future.md b/docs/zh/docs/history-design-future.md
index 56a15d003..798b8fb5f 100644
--- a/docs/zh/docs/history-design-future.md
+++ b/docs/zh/docs/history-design-future.md
@@ -53,7 +53,7 @@
## 需求项
-经过测试多种备选方案,我最终决定使用
**Pydantic**,并充分利用它的优势。
+经过测试多种备选方案,我最终决定使用
**Pydantic**,并充分利用它的优势。
我甚至为它做了不少贡献,让它完美兼容了 JSON Schema,支持多种方式定义约束声明,并基于多个编辑器,改进了它对编辑器支持(类型检查、自动补全)。
diff --git a/docs/zh/docs/index.md b/docs/zh/docs/index.md
index d776e5813..a480d6640 100644
--- a/docs/zh/docs/index.md
+++ b/docs/zh/docs/index.md
@@ -112,7 +112,7 @@ Python 3.8 及更高版本
FastAPI 站在以下巨人的肩膀之上:
*
Starlette 负责 web 部分。
-*
Pydantic 负责数据部分。
+*
Pydantic 负责数据部分。
## 安装
@@ -443,7 +443,7 @@ item: Item
*
httpx
- 使用 `TestClient` 时安装。
*
jinja2
- 使用默认模板配置时安装。
-*
python-multipart
- 需要通过 `request.form()` 对表单进行
「解析」时安装。
+*
python-multipart
- 需要通过 `request.form()` 对表单进行
「解析」时安装。
*
itsdangerous
- 需要 `SessionMiddleware` 支持时安装。
*
pyyaml
- 使用 Starlette 提供的 `SchemaGenerator` 时安装(有 FastAPI 你可能并不需要它)。
*
graphene
- 需要 `GraphQLApp` 支持时安装。
diff --git a/docs/zh/docs/python-types.md b/docs/zh/docs/python-types.md
index 6cdb4b588..214b47611 100644
--- a/docs/zh/docs/python-types.md
+++ b/docs/zh/docs/python-types.md
@@ -237,7 +237,7 @@ John Doe
## Pydantic 模型
-
Pydantic 是一个用来用来执行数据校验的 Python 库。
+
Pydantic 是一个用来用来执行数据校验的 Python 库。
你可以将数据的"结构"声明为具有属性的类。
@@ -254,7 +254,7 @@ John Doe
```
!!! info
- 想进一步了解
Pydantic,请阅读其文档.
+ 想进一步了解
Pydantic,请阅读其文档.
整个 **FastAPI** 建立在 Pydantic 的基础之上。
diff --git a/docs/zh/docs/tutorial/body-nested-models.md b/docs/zh/docs/tutorial/body-nested-models.md
index c65308bef..3f519ae33 100644
--- a/docs/zh/docs/tutorial/body-nested-models.md
+++ b/docs/zh/docs/tutorial/body-nested-models.md
@@ -182,7 +182,7 @@ Pydantic 模型的每个属性都具有类型。
除了普通的单一值类型(如 `str`、`int`、`float` 等)外,你还可以使用从 `str` 继承的更复杂的单一值类型。
-要了解所有的可用选项,请查看关于
来自 Pydantic 的外部类型 的文档。你将在下一章节中看到一些示例。
+要了解所有的可用选项,请查看关于
来自 Pydantic 的外部类型 的文档。你将在下一章节中看到一些示例。
例如,在 `Image` 模型中我们有一个 `url` 字段,我们可以把它声明为 Pydantic 的 `HttpUrl`,而不是 `str`:
diff --git a/docs/zh/docs/tutorial/body.md b/docs/zh/docs/tutorial/body.md
index 5cf53c0c2..3d615be39 100644
--- a/docs/zh/docs/tutorial/body.md
+++ b/docs/zh/docs/tutorial/body.md
@@ -6,7 +6,7 @@
你的 API 几乎总是要发送**响应**体。但是客户端并不总是需要发送**请求**体。
-我们使用
Pydantic 模型来声明**请求**体,并能够获得它们所具有的所有能力和优点。
+我们使用
Pydantic 模型来声明**请求**体,并能够获得它们所具有的所有能力和优点。
!!! info
你不能使用 `GET` 操作(HTTP 方法)发送请求体。
diff --git a/docs/zh/docs/tutorial/cookie-params.md b/docs/zh/docs/tutorial/cookie-params.md
index f115f9677..8571422dd 100644
--- a/docs/zh/docs/tutorial/cookie-params.md
+++ b/docs/zh/docs/tutorial/cookie-params.md
@@ -1,10 +1,10 @@
# Cookie 参数
-你可以像定义 `Query` 参数和 `Path` 参数一样来定义 `Cookie` 参数。
+ 定义 `Cookie` 参数与定义 `Query` 和 `Path` 参数一样。
## 导入 `Cookie`
-首先,导入 `Cookie`:
+首先,导入 `Cookie`:
=== "Python 3.10+"
@@ -44,9 +44,9 @@
## 声明 `Cookie` 参数
-声明 `Cookie` 参数的结构与声明 `Query` 参数和 `Path` 参数时相同。
+声明 `Cookie` 参数的方式与声明 `Query` 和 `Path` 参数相同。
-第一个值是参数的默认值,同时也可以传递所有验证参数或注释参数,来校验参数:
+第一个值是默认值,还可以传递所有验证参数或注释参数:
=== "Python 3.10+"
@@ -86,13 +86,15 @@
```
!!! note "技术细节"
- `Cookie` 、`Path` 、`Query`是兄弟类,它们都继承自公共的 `Param` 类
- 但请记住,当你从 `fastapi` 导入的 `Query`、`Path`、`Cookie` 或其他参数声明函数,这些实际上是返回特殊类的函数。
+ `Cookie` 、`Path` 、`Query` 是**兄弟类**,都继承自共用的 `Param` 类。
-!!! info
- 你需要使用 `Cookie` 来声明 cookie 参数,否则参数将会被解释为查询参数。
+ 注意,从 `fastapi` 导入的 `Query`、`Path`、`Cookie` 等对象,实际上是返回特殊类的函数。
-## 总结
+!!! info "说明"
-使用 `Cookie` 声明 cookie 参数,使用方式与 `Query` 和 `Path` 类似。
+ 必须使用 `Cookie` 声明 cookie 参数,否则该参数会被解释为查询参数。
+
+## 小结
+
+使用 `Cookie` 声明 cookie 参数的方式与 `Query` 和 `Path` 相同。
diff --git a/docs/zh/docs/tutorial/extra-data-types.md b/docs/zh/docs/tutorial/extra-data-types.md
index f4a77050c..cf39de0dd 100644
--- a/docs/zh/docs/tutorial/extra-data-types.md
+++ b/docs/zh/docs/tutorial/extra-data-types.md
@@ -36,7 +36,7 @@
* `datetime.timedelta`:
* 一个 Python `datetime.timedelta`.
* 在请求和响应中将表示为 `float` 代表总秒数。
- * Pydantic 也允许将其表示为 "ISO 8601 时间差异编码",
查看文档了解更多信息。
+ * Pydantic 也允许将其表示为 "ISO 8601 时间差异编码",
查看文档了解更多信息。
* `frozenset`:
* 在请求和响应中,作为 `set` 对待:
* 在请求中,列表将被读取,消除重复,并将其转换为一个 `set`。
@@ -49,7 +49,7 @@
* `Decimal`:
* 标准的 Python `Decimal`。
* 在请求和响应中被当做 `float` 一样处理。
-* 您可以在这里检查所有有效的pydantic数据类型:
Pydantic data types.
+* 您可以在这里检查所有有效的pydantic数据类型:
Pydantic data types.
## 例子
diff --git a/docs/zh/docs/tutorial/extra-models.md b/docs/zh/docs/tutorial/extra-models.md
index 06427a73d..94d82c524 100644
--- a/docs/zh/docs/tutorial/extra-models.md
+++ b/docs/zh/docs/tutorial/extra-models.md
@@ -1,21 +1,22 @@
-# 额外的模型
+# 更多模型
-我们从前面的示例继续,拥有多个相关的模型是很常见的。
+书接上文,多个关联模型这种情况很常见。
-对用户模型来说尤其如此,因为:
+特别是用户模型,因为:
-* **输入模型**需要拥有密码属性。
-* **输出模型**不应该包含密码。
-* **数据库模型**很可能需要保存密码的哈希值。
+* **输入模型**应该含密码
+* **输出模型**不应含密码
+* **数据库模型**需要加密的密码
-!!! danger
- 永远不要存储用户的明文密码。始终存储一个可以用于验证的「安全哈希值」。
+!!! danger "危险"
- 如果你尚未了解该知识,你可以在[安全章节](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}中学习何为「密码哈希值」。
+ 千万不要存储用户的明文密码。始终存储可以进行验证的**安全哈希值**。
+
+ 如果不了解这方面的知识,请参阅[安全性中的章节](security/simple-oauth2.md#password-hashing){.internal-link target=_blank},了解什么是**密码哈希**。
## 多个模型
-下面是应该如何根据它们的密码字段以及使用位置去定义模型的大概思路:
+下面的代码展示了不同模型处理密码字段的方式,及使用位置的大致思路:
=== "Python 3.10+"
@@ -29,35 +30,35 @@
{!> ../../../docs_src/extra_models/tutorial001.py!}
```
-### 关于 `**user_in.dict()`
+### `**user_in.dict()` 简介
#### Pydantic 的 `.dict()`
-`user_in` 是一个 `UserIn` 类的 Pydantic 模型.
+`user_in` 是类 `UserIn` 的 Pydantic 模型。
-Pydantic 模型具有 `.dict()` 方法,该方法返回一个拥有模型数据的 `dict`。
+Pydantic 模型支持 `.dict()` 方法,能返回包含模型数据的**字典**。
-因此,如果我们像下面这样创建一个 Pydantic 对象 `user_in`:
+因此,如果使用如下方式创建 Pydantic 对象 `user_in`:
```Python
user_in = UserIn(username="john", password="secret", email="john.doe@example.com")
```
-然后我们调用:
+就能以如下方式调用:
```Python
user_dict = user_in.dict()
```
-现在我们有了一个数据位于变量 `user_dict` 中的 `dict`(它是一个 `dict` 而不是 Pydantic 模型对象)。
+现在,变量 `user_dict`中的就是包含数据的**字典**(变量 `user_dict` 是字典,不是 Pydantic 模型对象)。
-如果我们调用:
+以如下方式调用:
```Python
print(user_dict)
```
-我们将获得一个这样的 Python `dict`:
+输出的就是 Python **字典**:
```Python
{
@@ -70,15 +71,15 @@ print(user_dict)
#### 解包 `dict`
-如果我们将 `user_dict` 这样的 `dict` 以 `**user_dict` 形式传递给一个函数(或类),Python将对其进行「解包」。它会将 `user_dict` 的键和值作为关键字参数直接传递。
+把**字典** `user_dict` 以 `**user_dict` 形式传递给函数(或类),Python 会执行**解包**操作。它会把 `user_dict` 的键和值作为关键字参数直接传递。
-因此,从上面的 `user_dict` 继续,编写:
+因此,接着上面的 `user_dict` 继续编写如下代码:
```Python
UserInDB(**user_dict)
```
-会产生类似于以下的结果:
+就会生成如下结果:
```Python
UserInDB(
@@ -89,7 +90,7 @@ UserInDB(
)
```
-或者更确切地,直接使用 `user_dict` 来表示将来可能包含的任何内容:
+或更精准,直接把可能会用到的内容与 `user_dict` 一起使用:
```Python
UserInDB(
@@ -100,34 +101,34 @@ UserInDB(
)
```
-#### 来自于其他模型内容的 Pydantic 模型
+#### 用其它模型中的内容生成 Pydantic 模型
-如上例所示,我们从 `user_in.dict()` 中获得了 `user_dict`,此代码:
+上例中 ,从 `user_in.dict()` 中得到了 `user_dict`,下面的代码:
```Python
user_dict = user_in.dict()
UserInDB(**user_dict)
```
-等同于:
+等效于:
```Python
UserInDB(**user_in.dict())
```
-...因为 `user_in.dict()` 是一个 `dict`,然后我们通过以`**`开头传递给 `UserInDB` 来使 Python「解包」它。
+……因为 `user_in.dict()` 是字典,在传递给 `UserInDB` 时,把 `**` 加在 `user_in.dict()` 前,可以让 Python 进行**解包**。
-这样,我们获得了一个来自于其他 Pydantic 模型中的数据的 Pydantic 模型。
+这样,就可以用其它 Pydantic 模型中的数据生成 Pydantic 模型。
-#### 解包 `dict` 和额外关键字
+#### 解包 `dict` 和更多关键字
-然后添加额外的关键字参数 `hashed_password=hashed_password`,例如:
+接下来,继续添加关键字参数 `hashed_password=hashed_password`,例如:
```Python
UserInDB(**user_in.dict(), hashed_password=hashed_password)
```
-...最终的结果如下:
+……输出结果如下:
```Python
UserInDB(
@@ -139,24 +140,27 @@ UserInDB(
)
```
-!!! warning
- 辅助性的额外函数只是为了演示可能的数据流,但它们显然不能提供任何真正的安全性。
+!!! warning "警告"
+
+ 辅助的附加函数只是为了演示可能的数据流,但它们显然不能提供任何真正的安全机制。
## 减少重复
-减少代码重复是 **FastAPI** 的核心思想之一。
+**FastAPI** 的核心思想就是减少代码重复。
+
+代码重复会导致 bug、安全问题、代码失步等问题(更新了某个位置的代码,但没有同步更新其它位置的代码)。
-因为代码重复会增加出现 bug、安全性问题、代码失步问题(当你在一个位置更新了代码但没有在其他位置更新)等的可能性。
+上面的这些模型共享了大量数据,拥有重复的属性名和类型。
-上面的这些模型都共享了大量数据,并拥有重复的属性名称和类型。
+FastAPI 可以做得更好。
-我们可以做得更好。
+声明 `UserBase` 模型作为其它模型的基类。然后,用该类衍生出继承其属性(类型声明、验证等)的子类。
-我们可以声明一个 `UserBase` 模型作为其他模型的基类。然后我们可以创建继承该模型属性(类型声明,校验等)的子类。
+所有数据转换、校验、文档等功能仍将正常运行。
-所有的数据转换、校验、文档生成等仍将正常运行。
+这样,就可以仅声明模型之间的差异部分(具有明文的 `password`、具有 `hashed_password` 以及不包括密码)。
-这样,我们可以仅声明模型之间的差异部分(具有明文的 `password`、具有 `hashed_password` 以及不包括密码)。
+通过这种方式,可以只声明模型之间的区别(分别包含明文密码、哈希密码,以及无密码的模型)。
=== "Python 3.10+"
@@ -172,15 +176,15 @@ UserInDB(
## `Union` 或者 `anyOf`
-你可以将一个响应声明为两种类型的 `Union`,这意味着该响应将是两种类型中的任何一种。
+响应可以声明为两种类型的 `Union` 类型,即该响应可以是两种类型中的任意类型。
-这将在 OpenAPI 中使用 `anyOf` 进行定义。
+在 OpenAPI 中可以使用 `anyOf` 定义。
-为此,请使用标准的 Python 类型提示
`typing.Union`:
+为此,请使用 Python 标准类型提示
`typing.Union`:
+!!! note "笔记"
-!!! note
- 定义一个
`Union` 类型时,首先包括最详细的类型,然后是不太详细的类型。在下面的示例中,更详细的 `PlaneItem` 位于 `Union[PlaneItem,CarItem]` 中的 `CarItem` 之前。
+ 定义
`Union` 类型时,要把详细的类型写在前面,然后是不太详细的类型。下例中,更详细的 `PlaneItem` 位于 `Union[PlaneItem,CarItem]` 中的 `CarItem` 之前。
=== "Python 3.10+"
@@ -196,7 +200,7 @@ UserInDB(
## 模型列表
-你可以用同样的方式声明由对象列表构成的响应。
+使用同样的方式也可以声明由对象列表构成的响应。
为此,请使用标准的 Python `typing.List`:
@@ -214,11 +218,11 @@ UserInDB(
## 任意 `dict` 构成的响应
-你还可以使用一个任意的普通 `dict` 声明响应,仅声明键和值的类型,而不使用 Pydantic 模型。
+任意的 `dict` 都能用于声明响应,只要声明键和值的类型,无需使用 Pydantic 模型。
-如果你事先不知道有效的字段/属性名称(对于 Pydantic 模型是必需的),这将很有用。
+事先不知道可用的字段 / 属性名时(Pydantic 模型必须知道字段是什么),这种方式特别有用。
-在这种情况下,你可以使用 `typing.Dict`:
+此时,可以使用 `typing.Dict`:
=== "Python 3.9+"
@@ -232,8 +236,8 @@ UserInDB(
{!> ../../../docs_src/extra_models/tutorial005.py!}
```
-## 总结
+## 小结
-使用多个 Pydantic 模型,并针对不同场景自由地继承。
+针对不同场景,可以随意使用不同的 Pydantic 模型继承定义的基类。
-如果一个实体必须能够具有不同的「状态」,你无需为每个状态的实体定义单独的数据模型。以用户「实体」为例,其状态有包含 `password`、包含 `password_hash` 以及不含密码。
+实体必须具有不同的**状态**时,不必为不同状态的实体单独定义数据模型。例如,用户**实体**就有包含 `password`、包含 `password_hash` 以及不含密码等多种状态。
diff --git a/docs/zh/docs/tutorial/handling-errors.md b/docs/zh/docs/tutorial/handling-errors.md
index a0d66e557..701cd241e 100644
--- a/docs/zh/docs/tutorial/handling-errors.md
+++ b/docs/zh/docs/tutorial/handling-errors.md
@@ -179,7 +179,7 @@ path -> item_id
如果您觉得现在还用不到以下技术细节,可以先跳过下面的内容。
-`RequestValidationError` 是 Pydantic 的
`ValidationError` 的子类。
+`RequestValidationError` 是 Pydantic 的
`ValidationError` 的子类。
**FastAPI** 调用的就是 `RequestValidationError` 类,因此,如果在 `response_model` 中使用 Pydantic 模型,且数据有错误时,在日志中就会看到这个错误。
diff --git a/docs/zh/docs/tutorial/header-params.md b/docs/zh/docs/tutorial/header-params.md
index 2701167b3..25dfeba87 100644
--- a/docs/zh/docs/tutorial/header-params.md
+++ b/docs/zh/docs/tutorial/header-params.md
@@ -1,10 +1,10 @@
# Header 参数
-你可以使用定义 `Query`, `Path` 和 `Cookie` 参数一样的方法定义 Header 参数。
+定义 `Header` 参数的方式与定义 `Query`、`Path`、`Cookie` 参数相同。
## 导入 `Header`
-首先导入 `Header`:
+首先,导入 `Header`:
=== "Python 3.10+"
@@ -44,9 +44,9 @@
## 声明 `Header` 参数
-然后使用和`Path`, `Query` and `Cookie` 一样的结构定义 header 参数
+然后,使用和 `Path`、`Query`、`Cookie` 一样的结构定义 header 参数。
-第一个值是默认值,你可以传递所有的额外验证或注释参数:
+第一个值是默认值,还可以传递所有验证参数或注释参数:
=== "Python 3.10+"
@@ -85,28 +85,30 @@
```
!!! note "技术细节"
- `Header` 是 `Path`, `Query` 和 `Cookie` 的兄弟类型。它也继承自通用的 `Param` 类.
- 但是请记得,当你从`fastapi`导入 `Query`, `Path`, `Header`, 或其他时,实际上导入的是返回特定类型的函数。
+ `Header` 是 `Path`、`Query`、`Cookie` 的**兄弟类**,都继承自共用的 `Param` 类。
-!!! info
- 为了声明headers, 你需要使用`Header`, 因为否则参数将被解释为查询参数。
+ 注意,从 `fastapi` 导入的 `Query`、`Path`、`Header` 等对象,实际上是返回特殊类的函数。
+
+!!! info "说明"
+
+ 必须使用 `Header` 声明 header 参数,否则该参数会被解释为查询参数。
## 自动转换
-`Header` 在 `Path`, `Query` 和 `Cookie` 提供的功能之上有一点额外的功能。
+`Header` 比 `Path`、`Query` 和 `Cookie` 提供了更多功能。
-大多数标准的headers用 "连字符" 分隔,也称为 "减号" (`-`)。
+大部分标准请求头用**连字符**分隔,即**减号**(`-`)。
-但是像 `user-agent` 这样的变量在Python中是无效的。
+但是 `user-agent` 这样的变量在 Python 中是无效的。
-因此, 默认情况下, `Header` 将把参数名称的字符从下划线 (`_`) 转换为连字符 (`-`) 来提取并记录 headers.
+因此,默认情况下,`Header` 把参数名中的字符由下划线(`_`)改为连字符(`-`)来提取并存档请求头 。
-同时,HTTP headers 是大小写不敏感的,因此,因此可以使用标准Python样式(也称为 "snake_case")声明它们。
+同时,HTTP 的请求头不区分大小写,可以使用 Python 标准样式(即 **snake_case**)进行声明。
-因此,您可以像通常在Python代码中那样使用 `user_agent` ,而不需要将首字母大写为 `User_Agent` 或类似的东西。
+因此,可以像在 Python 代码中一样使用 `user_agent` ,无需把首字母大写为 `User_Agent` 等形式。
-如果出于某些原因,你需要禁用下划线到连字符的自动转换,设置`Header`的参数 `convert_underscores` 为 `False`:
+如需禁用下划线自动转换为连字符,可以把 `Header` 的 `convert_underscores` 参数设置为 `False`:
=== "Python 3.10+"
@@ -144,19 +146,20 @@
{!> ../../../docs_src/header_params/tutorial002.py!}
```
-!!! warning
- 在设置 `convert_underscores` 为 `False` 之前,请记住,一些HTTP代理和服务器不允许使用带有下划线的headers。
+!!! warning "警告"
+
+ 注意,使用 `convert_underscores = False` 要慎重,有些 HTTP 代理和服务器不支持使用带有下划线的请求头。
-## 重复的 headers
+## 重复的请求头
-有可能收到重复的headers。这意味着,相同的header具有多个值。
+有时,可能需要接收重复的请求头。即同一个请求头有多个值。
-您可以在类型声明中使用一个list来定义这些情况。
+类型声明中可以使用 `list` 定义多个请求头。
-你可以通过一个Python `list` 的形式获得重复header的所有值。
+使用 Python `list` 可以接收重复请求头所有的值。
-比如, 为了声明一个 `X-Token` header 可以出现多次,你可以这样写:
+例如,声明 `X-Token` 多次出现的请求头,可以写成这样:
=== "Python 3.10+"
@@ -203,14 +206,14 @@
{!> ../../../docs_src/header_params/tutorial003.py!}
```
-如果你与*路径操作*通信时发送两个HTTP headers,就像:
+与*路径操作*通信时,以下面的方式发送两个 HTTP 请求头:
```
X-Token: foo
X-Token: bar
```
-响应会是:
+响应结果是:
```JSON
{
@@ -221,8 +224,8 @@ X-Token: bar
}
```
-## 回顾
+## 小结
-使用 `Header` 来声明 header , 使用和 `Query`, `Path` 与 `Cookie` 相同的模式。
+使用 `Header` 声明请求头的方式与 `Query`、`Path` 、`Cookie` 相同。
-不用担心变量中的下划线,**FastAPI** 会负责转换它们。
+不用担心变量中的下划线,**FastAPI** 可以自动转换。
diff --git a/docs/zh/docs/tutorial/metadata.md b/docs/zh/docs/tutorial/metadata.md
index 3e669bc72..8170e6ecc 100644
--- a/docs/zh/docs/tutorial/metadata.md
+++ b/docs/zh/docs/tutorial/metadata.md
@@ -1,40 +1,36 @@
# 元数据和文档 URL
-你可以在 **FastAPI** 应用中自定义几个元数据配置。
+你可以在 FastAPI 应用程序中自定义多个元数据配置。
-## 标题、描述和版本
+## API 元数据
-你可以设定:
+你可以在设置 OpenAPI 规范和自动 API 文档 UI 中使用的以下字段:
-* **Title**:在 OpenAPI 和自动 API 文档用户界面中作为 API 的标题/名称使用。
-* **Description**:在 OpenAPI 和自动 API 文档用户界面中用作 API 的描述。
-* **Version**:API 版本,例如 `v2` 或者 `2.5.0`。
- * 如果你之前的应用程序版本也使用 OpenAPI 会很有用。
+| 参数 | 类型 | 描述 |
+|------------|------|-------------|
+| `title` | `str` | API 的标题。 |
+| `summary` | `str` | API 的简短摘要。
自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。. |
+| `description` | `str` | API 的简短描述。可以使用Markdown。 |
+| `version` | `string` | API 的版本。这是您自己的应用程序的版本,而不是 OpenAPI 的版本。例如 `2.5.0` 。 |
+| `terms_of_service` | `str` | API 服务条款的 URL。如果提供,则必须是 URL。 |
+| `contact` | `dict` | 公开的 API 的联系信息。它可以包含多个字段。
contact
字段
参数 | Type | 描述 |
---|
name | str | 联系人/组织的识别名称。 |
url | str | 指向联系信息的 URL。必须采用 URL 格式。 |
email | str | 联系人/组织的电子邮件地址。必须采用电子邮件地址的格式。 |
|
+| `license_info` | `dict` | 公开的 API 的许可证信息。它可以包含多个字段。
license_info
字段
参数 | 类型 | 描述 |
---|
name | str | 必须的 (如果设置了license_info ). 用于 API 的许可证名称。 |
identifier | str | 一个API的SPDX许可证表达。 The identifier field is mutually exclusive of the url field. 自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。 |
url | str | 用于 API 的许可证的 URL。必须采用 URL 格式。 |
|
-使用 `title`、`description` 和 `version` 来设置它们:
+你可以按如下方式设置它们:
```Python hl_lines="4-6"
{!../../../docs_src/metadata/tutorial001.py!}
```
+!!! tip
+ 您可以在 `description` 字段中编写 Markdown,它将在输出中呈现。
+
通过这样设置,自动 API 文档看起来会像:

## 标签元数据
-你也可以使用参数 `openapi_tags`,为用于分组路径操作的不同标签添加额外的元数据。
-
-它接受一个列表,这个列表包含每个标签对应的一个字典。
-
-每个字典可以包含:
-
-* `name`(**必要**):一个 `str`,它与*路径操作*和 `APIRouter` 中使用的 `tags` 参数有相同的标签名。
-* `description`:一个用于简短描述标签的 `str`。它支持 Markdown 并且会在文档用户界面中显示。
-* `externalDocs`:一个描述外部文档的 `dict`:
- * `description`:用于简短描述外部文档的 `str`。
- * `url`(**必要**):外部文档的 URL `str`。
-
### 创建标签元数据
让我们在带有标签的示例中为 `users` 和 `items` 试一下。
@@ -59,7 +55,7 @@
```
!!! 信息
- 阅读更多关于标签的信息[路径操作配置](../path-operation-configuration/#tags){.internal-link target=_blank}。
+ 阅读更多关于标签的信息[路径操作配置](path-operation-configuration.md#tags){.internal-link target=_blank}。
### 查看文档
diff --git a/docs/zh/docs/tutorial/path-params.md b/docs/zh/docs/tutorial/path-params.md
index 1b428d662..5bb4eba80 100644
--- a/docs/zh/docs/tutorial/path-params.md
+++ b/docs/zh/docs/tutorial/path-params.md
@@ -93,7 +93,7 @@
## Pydantic
-所有的数据校验都由
Pydantic 在幕后完成,所以你可以从它所有的优点中受益。并且你知道它在这方面非常胜任。
+所有的数据校验都由
Pydantic 在幕后完成,所以你可以从它所有的优点中受益。并且你知道它在这方面非常胜任。
你可以使用同样的类型声明来声明 `str`、`float`、`bool` 以及许多其他的复合数据类型。
diff --git a/docs/zh/docs/tutorial/query-params-str-validations.md b/docs/zh/docs/tutorial/query-params-str-validations.md
index 39253eb0d..af0428837 100644
--- a/docs/zh/docs/tutorial/query-params-str-validations.md
+++ b/docs/zh/docs/tutorial/query-params-str-validations.md
@@ -152,7 +152,7 @@ q: Union[str, None] = Query(default=None, min_length=3)
```
!!! tip
- Pydantic 是 FastAPI 中所有数据验证和序列化的核心,当你在没有设默认值的情况下使用 `Optional` 或 `Union[Something, None]` 时,它具有特殊行为,你可以在 Pydantic 文档中阅读有关
必需可选字段的更多信息。
+ Pydantic 是 FastAPI 中所有数据验证和序列化的核心,当你在没有设默认值的情况下使用 `Optional` 或 `Union[Something, None]` 时,它具有特殊行为,你可以在 Pydantic 文档中阅读有关
必需可选字段的更多信息。
### 使用Pydantic中的`Required`代替省略号(`...`)
diff --git a/docs/zh/docs/tutorial/query-params.md b/docs/zh/docs/tutorial/query-params.md
index b1668a2d2..a0cc7fea3 100644
--- a/docs/zh/docs/tutorial/query-params.md
+++ b/docs/zh/docs/tutorial/query-params.md
@@ -63,9 +63,18 @@ http://127.0.0.1:8000/items/?skip=20
通过同样的方式,你可以将它们的默认值设置为 `None` 来声明可选查询参数:
-```Python hl_lines="7"
-{!../../../docs_src/query_params/tutorial002.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.8+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params/tutorial002.py!}
+ ```
+
在这个例子中,函数参数 `q` 将是可选的,并且默认值为 `None`。
diff --git a/docs/zh/docs/tutorial/request-files.md b/docs/zh/docs/tutorial/request-files.md
index 2c48f33ca..1cd3518cf 100644
--- a/docs/zh/docs/tutorial/request-files.md
+++ b/docs/zh/docs/tutorial/request-files.md
@@ -6,7 +6,7 @@
因为上传文件以「表单数据」形式发送。
- 所以接收上传文件,要预先安装
`python-multipart`。
+ 所以接收上传文件,要预先安装
`python-multipart`。
例如: `pip install python-multipart`。
diff --git a/docs/zh/docs/tutorial/request-forms-and-files.md b/docs/zh/docs/tutorial/request-forms-and-files.md
index 70cd70f98..f58593669 100644
--- a/docs/zh/docs/tutorial/request-forms-and-files.md
+++ b/docs/zh/docs/tutorial/request-forms-and-files.md
@@ -4,7 +4,7 @@ FastAPI 支持同时使用 `File` 和 `Form` 定义文件和表单字段。
!!! info "说明"
- 接收上传文件或表单数据,要预先安装
`python-multipart`。
+ 接收上传文件或表单数据,要预先安装
`python-multipart`。
例如,`pip install python-multipart`。
diff --git a/docs/zh/docs/tutorial/request-forms.md b/docs/zh/docs/tutorial/request-forms.md
index 6436ffbcd..e4fcd88ff 100644
--- a/docs/zh/docs/tutorial/request-forms.md
+++ b/docs/zh/docs/tutorial/request-forms.md
@@ -4,7 +4,7 @@
!!! info "说明"
- 要使用表单,需预先安装
`python-multipart`。
+ 要使用表单,需预先安装
`python-multipart`。
例如,`pip install python-multipart`。
diff --git a/docs/zh/docs/tutorial/response-model.md b/docs/zh/docs/tutorial/response-model.md
index e731b6989..0f1b3b4b9 100644
--- a/docs/zh/docs/tutorial/response-model.md
+++ b/docs/zh/docs/tutorial/response-model.md
@@ -160,7 +160,7 @@ FastAPI 将使用此 `response_model` 来:
```
!!! info
- FastAPI 通过 Pydantic 模型的 `.dict()` 配合
该方法的 `exclude_unset` 参数 来实现此功能。
+ FastAPI 通过 Pydantic 模型的 `.dict()` 配合
该方法的 `exclude_unset` 参数 来实现此功能。
!!! info
你还可以使用:
@@ -168,7 +168,7 @@ FastAPI 将使用此 `response_model` 来:
* `response_model_exclude_defaults=True`
* `response_model_exclude_none=True`
- 参考
Pydantic 文档 中对 `exclude_defaults` 和 `exclude_none` 的描述。
+ 参考
Pydantic 文档 中对 `exclude_defaults` 和 `exclude_none` 的描述。
#### 默认值字段有实际值的数据
diff --git a/docs/zh/docs/tutorial/response-status-code.md b/docs/zh/docs/tutorial/response-status-code.md
index 357831942..cc23231b4 100644
--- a/docs/zh/docs/tutorial/response-status-code.md
+++ b/docs/zh/docs/tutorial/response-status-code.md
@@ -1,89 +1,95 @@
# 响应状态码
-与指定响应模型的方式相同,你也可以在以下任意的*路径操作*中使用 `status_code` 参数来声明用于响应的 HTTP 状态码:
+与指定响应模型的方式相同,在以下任意*路径操作*中,可以使用 `status_code` 参数声明用于响应的 HTTP 状态码:
* `@app.get()`
* `@app.post()`
* `@app.put()`
* `@app.delete()`
-* 等等。
+* 等……
```Python hl_lines="6"
{!../../../docs_src/response_status_code/tutorial001.py!}
```
-!!! note
- 注意,`status_code` 是「装饰器」方法(`get`,`post` 等)的一个参数。不像之前的所有参数和请求体,它不属于*路径操作函数*。
+!!! note "笔记"
-`status_code` 参数接收一个表示 HTTP 状态码的数字。
+ 注意,`status_code` 是(`get`、`post` 等)**装饰器**方法中的参数。与之前的参数和请求体不同,不是*路径操作函数*的参数。
-!!! info
- `status_code` 也能够接收一个 `IntEnum` 类型,比如 Python 的
`http.HTTPStatus`。
+`status_code` 参数接收表示 HTTP 状态码的数字。
-它将会:
+!!! info "说明"
-* 在响应中返回该状态码。
-* 在 OpenAPI 模式中(以及在用户界面中)将其记录为:
+ `status_code` 还能接收 `IntEnum` 类型,比如 Python 的
`http.HTTPStatus`。
-

+它可以:
-!!! note
- 一些响应状态码(请参阅下一部分)表示响应没有响应体。
+* 在响应中返回状态码
+* 在 OpenAPI 概图(及用户界面)中存档:
- FastAPI 知道这一点,并将生成表明没有响应体的 OpenAPI 文档。
+

+
+!!! note "笔记"
+
+ 某些响应状态码表示响应没有响应体(参阅下一章)。
+
+ FastAPI 可以进行识别,并生成表明无响应体的 OpenAPI 文档。
## 关于 HTTP 状态码
-!!! note
- 如果你已经了解什么是 HTTP 状态码,请跳到下一部分。
+!!! note "笔记"
-在 HTTP 协议中,你将发送 3 位数的数字状态码作为响应的一部分。
+ 如果已经了解 HTTP 状态码,请跳到下一章。
-这些状态码有一个识别它们的关联名称,但是重要的还是数字。
+在 HTTP 协议中,发送 3 位数的数字状态码是响应的一部分。
-简而言之:
+这些状态码都具有便于识别的关联名称,但是重要的还是数字。
-* `100` 及以上状态码用于「消息」响应。你很少直接使用它们。具有这些状态代码的响应不能带有响应体。
-* **`200`** 及以上状态码用于「成功」响应。这些是你最常使用的。
- * `200` 是默认状态代码,它表示一切「正常」。
- * 另一个例子会是 `201`,「已创建」。它通常在数据库中创建了一条新记录后使用。
- * 一个特殊的例子是 `204`,「无内容」。此响应在没有内容返回给客户端时使用,因此该响应不能包含响应体。
-* **`300`** 及以上状态码用于「重定向」。具有这些状态码的响应可能有或者可能没有响应体,但 `304`「未修改」是个例外,该响应不得含有响应体。
-* **`400`** 及以上状态码用于「客户端错误」响应。这些可能是你第二常使用的类型。
- * 一个例子是 `404`,用于「未找到」响应。
- * 对于来自客户端的一般错误,你可以只使用 `400`。
-* `500` 及以上状态码用于服务器端错误。你几乎永远不会直接使用它们。当你的应用程序代码或服务器中的某些部分出现问题时,它将自动返回这些状态代码之一。
+简言之:
-!!! tip
- 要了解有关每个状态代码以及适用场景的更多信息,请查看
MDN 关于 HTTP 状态码的文档。
+* `100` 及以上的状态码用于返回**信息**。这类状态码很少直接使用。具有这些状态码的响应不能包含响应体
+* **`200`** 及以上的状态码用于表示**成功**。这些状态码是最常用的
+ * `200` 是默认状态代码,表示一切**正常**
+ * `201` 表示**已创建**,通常在数据库中创建新记录后使用
+ * `204` 是一种特殊的例子,表示**无内容**。该响应在没有为客户端返回内容时使用,因此,该响应不能包含响应体
+* **`300`** 及以上的状态码用于**重定向**。具有这些状态码的响应不一定包含响应体,但 `304`**未修改**是个例外,该响应不得包含响应体
+* **`400`** 及以上的状态码用于表示**客户端错误**。这些可能是第二常用的类型
+ * `404`,用于**未找到**响应
+ * 对于来自客户端的一般错误,可以只使用 `400`
+* `500` 及以上的状态码用于表示服务器端错误。几乎永远不会直接使用这些状态码。应用代码或服务器出现问题时,会自动返回这些状态代码
-## 记住名称的捷径
+!!! tip "提示"
-让我们再次看看之前的例子:
+ 状态码及适用场景的详情,请参阅
MDN 的 HTTP 状态码文档。
+
+## 状态码名称快捷方式
+
+再看下之前的例子:
```Python hl_lines="6"
{!../../../docs_src/response_status_code/tutorial001.py!}
```
-`201` 是表示「已创建」的状态码。
+`201` 表示**已创建**的状态码。
-但是你不必去记住每个代码的含义。
+但我们没有必要记住所有代码的含义。
-你可以使用来自 `fastapi.status` 的便捷变量。
+可以使用 `fastapi.status` 中的快捷变量。
```Python hl_lines="1 6"
{!../../../docs_src/response_status_code/tutorial002.py!}
```
-它们只是一种便捷方式,它们具有同样的数字代码,但是这样使用你就可以使用编辑器的自动补全功能来查找它们:
+这只是一种快捷方式,具有相同的数字代码,但它可以使用编辑器的自动补全功能:
-

+

!!! note "技术细节"
- 你也可以使用 `from starlette import status`。
- 为了给你(即开发者)提供方便,**FastAPI** 提供了与 `starlette.status` 完全相同的 `fastapi.status`。但它直接来自于 Starlette。
+ 也可以使用 `from starlette import status`。
+
+ 为了让开发者更方便,**FastAPI** 提供了与 `starlette.status` 完全相同的 `fastapi.status`。但它直接来自于 Starlette。
## 更改默认状态码
-稍后,在[高级用户指南](../advanced/response-change-status-code.md){.internal-link target=_blank}中你将了解如何返回与在此声明的默认状态码不同的状态码。
+[高级用户指南](../advanced/response-change-status-code.md){.internal-link target=_blank}中,将介绍如何返回与在此声明的默认状态码不同的状态码。
diff --git a/docs/zh/docs/tutorial/schema-extra-example.md b/docs/zh/docs/tutorial/schema-extra-example.md
index ebc04da8b..ae204dc61 100644
--- a/docs/zh/docs/tutorial/schema-extra-example.md
+++ b/docs/zh/docs/tutorial/schema-extra-example.md
@@ -8,7 +8,7 @@
## Pydantic `schema_extra`
-您可以使用 `Config` 和 `schema_extra` 为Pydantic模型声明一个示例,如
Pydantic 文档:定制 Schema 中所述:
+您可以使用 `Config` 和 `schema_extra` 为Pydantic模型声明一个示例,如
Pydantic 文档:定制 Schema 中所述:
=== "Python 3.10+"
diff --git a/docs/zh/docs/tutorial/security/first-steps.md b/docs/zh/docs/tutorial/security/first-steps.md
index dda956417..f28cc24f8 100644
--- a/docs/zh/docs/tutorial/security/first-steps.md
+++ b/docs/zh/docs/tutorial/security/first-steps.md
@@ -45,7 +45,7 @@
!!! info "说明"
- 先安装
`python-multipart`。
+ 先安装
`python-multipart`。
安装命令: `pip install python-multipart`。
diff --git a/docs/zh/docs/tutorial/security/get-current-user.md b/docs/zh/docs/tutorial/security/get-current-user.md
index 477baec3a..1f17f5bd9 100644
--- a/docs/zh/docs/tutorial/security/get-current-user.md
+++ b/docs/zh/docs/tutorial/security/get-current-user.md
@@ -1,35 +1,35 @@
# 获取当前用户
-在上一章节中,(基于依赖项注入系统的)安全系统向*路径操作函数*提供了一个 `str` 类型的 `token`:
+上一章中,(基于依赖注入系统的)安全系统向*路径操作函数*传递了 `str` 类型的 `token`:
```Python hl_lines="10"
{!../../../docs_src/security/tutorial001.py!}
```
-但这还不是很实用。
+但这并不实用。
-让我们来使它返回当前用户给我们。
+接下来,我们学习如何返回当前用户。
-## 创建一个用户模型
+## 创建用户模型
-首先,让我们来创建一个用户 Pydantic 模型。
+首先,创建 Pydantic 用户模型。
-与使用 Pydantic 声明请求体的方式相同,我们可以在其他任何地方使用它:
+与使用 Pydantic 声明请求体相同,并且可在任何位置使用:
```Python hl_lines="5 12-16"
{!../../../docs_src/security/tutorial002.py!}
```
-## 创建一个 `get_current_user` 依赖项
+## 创建 `get_current_user` 依赖项
-让我们来创建一个 `get_current_user` 依赖项。
+创建 `get_current_user` 依赖项。
-还记得依赖项可以有子依赖项吗?
+还记得依赖项支持子依赖项吗?
-`get_current_user` 将具有一个我们之前所创建的同一个 `oauth2_scheme` 作为依赖项。
+`get_current_user` 使用 `oauth2_scheme` 作为依赖项。
-与我们之前直接在路径操作中所做的相同,我们新的依赖项 `get_current_user` 将从子依赖项 `oauth2_scheme` 中接收一个 `str` 类型的 `token`:
+与之前直接在路径操作中的做法相同,新的 `get_current_user` 依赖项从子依赖项 `oauth2_scheme` 中接收 `str` 类型的 `token`:
```Python hl_lines="25"
{!../../../docs_src/security/tutorial002.py!}
@@ -37,7 +37,7 @@
## 获取用户
-`get_current_user` 将使用我们创建的(伪)工具函数,该函数接收 `str` 类型的令牌并返回我们的 Pydantic `User` 模型:
+`get_current_user` 使用创建的(伪)工具函数,该函数接收 `str` 类型的令牌,并返回 Pydantic 的 `User` 模型:
```Python hl_lines="19-22 26-27"
{!../../../docs_src/security/tutorial002.py!}
@@ -45,70 +45,72 @@
## 注入当前用户
-因此现在我们可以在*路径操作*中使用 `get_current_user` 作为 `Depends` 了:
+在*路径操作* 的 `Depends` 中使用 `get_current_user`:
```Python hl_lines="31"
{!../../../docs_src/security/tutorial002.py!}
```
-注意我们将 `current_user` 的类型声明为 Pydantic 模型 `User`。
+注意,此处把 `current_user` 的类型声明为 Pydantic 的 `User` 模型。
-这将帮助我们在函数内部使用所有的代码补全和类型检查。
+这有助于在函数内部使用代码补全和类型检查。
-!!! tip
- 你可能还记得请求体也是使用 Pydantic 模型来声明的。
+!!! tip "提示"
- 在这里 **FastAPI** 不会搞混,因为你正在使用的是 `Depends`。
+ 还记得请求体也是使用 Pydantic 模型声明的吧。
-!!! check
- 这种依赖系统的设计方式使我们可以拥有不同的依赖项(不同的「可依赖类型」),并且它们都返回一个 `User` 模型。
+ 放心,因为使用了 `Depends`,**FastAPI** 不会搞混。
- 我们并未被局限于只能有一个返回该类型数据的依赖项。
+!!! check "检查"
+ 依赖系统的这种设计方式可以支持不同的依赖项返回同一个 `User` 模型。
-## 其他模型
+ 而不是局限于只能有一个返回该类型数据的依赖项。
-现在你可以直接在*路径操作函数*中获取当前用户,并使用 `Depends` 在**依赖注入**级别处理安全性机制。
-你可以使用任何模型或数据来满足安全性要求(在这个示例中,使用的是 Pydantic 模型 `User`)。
+## 其它模型
-但是你并未被限制只能使用某些特定的数据模型,类或类型。
+接下来,直接在*路径操作函数*中获取当前用户,并用 `Depends` 在**依赖注入**系统中处理安全机制。
-你想要在模型中使用 `id` 和 `email` 而不使用任何的 `username`?当然可以。你可以同样地使用这些工具。
+开发者可以使用任何模型或数据满足安全需求(本例中是 Pydantic 的 `User` 模型)。
-你只想要一个 `str`?或者仅仅一个 `dict`?还是直接一个数据库模型类的实例?它们的工作方式都是一样的。
+而且,不局限于只能使用特定的数据模型、类或类型。
-实际上你没有用户登录到你的应用程序,而是只拥有访问令牌的机器人,程序或其他系统?再一次,它们的工作方式也是一样的。
+不想在模型中使用 `username`,而是使用 `id` 和 `email`?当然可以。这些工具也支持。
-尽管去使用你的应用程序所需要的任何模型,任何类,任何数据库。**FastAPI** 通过依赖项注入系统都帮你搞定。
+只想使用字符串?或字典?甚至是数据库类模型的实例?工作方式都一样。
+实际上,就算登录应用的不是用户,而是只拥有访问令牌的机器人、程序或其它系统?工作方式也一样。
-## 代码体积
+尽管使用应用所需的任何模型、类、数据库。**FastAPI** 通过依赖注入系统都能帮您搞定。
-这个示例似乎看起来很冗长。考虑到我们在同一文件中混合了安全性,数据模型工具函数和路径操作等代码。
-但关键的是。
+## 代码大小
-安全性和依赖项注入内容只需要编写一次。
+这个示例看起来有些冗长。毕竟这个文件同时包含了安全、数据模型的工具函数,以及路径操作等代码。
-你可以根据需要使其变得很复杂。而且只需要在一个地方写一次。但仍然具备所有的灵活性。
+但,关键是:
-但是,你可以有无数个使用同一安全系统的端点(*路径操作*)。
+**安全和依赖注入的代码只需要写一次。**
-所有(或所需的任何部分)的端点,都可以利用对这些或你创建的其他依赖项进行复用所带来的优势。
+就算写得再复杂,也只是在一个位置写一次就够了。所以,要多复杂就可以写多复杂。
-所有的这无数个*路径操作*甚至可以小到只需 3 行代码:
+但是,就算有数千个端点(*路径操作*),它们都可以使用同一个安全系统。
+
+而且,所有端点(或它们的任何部件)都可以利用这些依赖项或任何其它依赖项。
+
+所有*路径操作*只需 3 行代码就可以了:
```Python hl_lines="30-32"
{!../../../docs_src/security/tutorial002.py!}
```
-## 总结
+## 小结
-现在你可以直接在*路径操作函数*中获取当前用户。
+现在,我们可以直接在*路径操作函数*中获取当前用户。
-我们已经进行到一半了。
+至此,安全的内容已经讲了一半。
-我们只需要再为用户/客户端添加一个真正发送 `username` 和 `password` 的*路径操作*。
+只要再为用户或客户端的*路径操作*添加真正发送 `username` 和 `password` 的功能就可以了。
-这些内容在下一章节。
+下一章见。
diff --git a/docs/zh/docs/tutorial/sql-databases.md b/docs/zh/docs/tutorial/sql-databases.md
index c49374971..be0c76593 100644
--- a/docs/zh/docs/tutorial/sql-databases.md
+++ b/docs/zh/docs/tutorial/sql-databases.md
@@ -329,7 +329,7 @@ name: str
现在,在用于查询的 Pydantic*模型*`Item`中`User`,添加一个内部`Config`类。
-此类[`Config`](https://pydantic-docs.helpmanual.io/usage/model_config/)用于为 Pydantic 提供配置。
+此类[`Config`](https://docs.pydantic.dev/latest/api/config/)用于为 Pydantic 提供配置。
在`Config`类中,设置属性`orm_mode = True`。
diff --git a/docs_src/app_testing/app_b/test_main.py b/docs_src/app_testing/app_b/test_main.py
index 4e2b98e23..4e1c51ecc 100644
--- a/docs_src/app_testing/app_b/test_main.py
+++ b/docs_src/app_testing/app_b/test_main.py
@@ -21,7 +21,7 @@ def test_read_item_bad_token():
assert response.json() == {"detail": "Invalid X-Token header"}
-def test_read_inexistent_item():
+def test_read_nonexistent_item():
response = client.get("/items/baz", headers={"X-Token": "coneofsilence"})
assert response.status_code == 404
assert response.json() == {"detail": "Item not found"}
diff --git a/docs_src/app_testing/app_b_an/test_main.py b/docs_src/app_testing/app_b_an/test_main.py
index d186b8ecb..e2eda449d 100644
--- a/docs_src/app_testing/app_b_an/test_main.py
+++ b/docs_src/app_testing/app_b_an/test_main.py
@@ -21,7 +21,7 @@ def test_read_item_bad_token():
assert response.json() == {"detail": "Invalid X-Token header"}
-def test_read_inexistent_item():
+def test_read_nonexistent_item():
response = client.get("/items/baz", headers={"X-Token": "coneofsilence"})
assert response.status_code == 404
assert response.json() == {"detail": "Item not found"}
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
index d186b8ecb..e2eda449d 100644
--- a/docs_src/app_testing/app_b_an_py310/test_main.py
+++ b/docs_src/app_testing/app_b_an_py310/test_main.py
@@ -21,7 +21,7 @@ def test_read_item_bad_token():
assert response.json() == {"detail": "Invalid X-Token header"}
-def test_read_inexistent_item():
+def test_read_nonexistent_item():
response = client.get("/items/baz", headers={"X-Token": "coneofsilence"})
assert response.status_code == 404
assert response.json() == {"detail": "Item not found"}
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
index d186b8ecb..e2eda449d 100644
--- a/docs_src/app_testing/app_b_an_py39/test_main.py
+++ b/docs_src/app_testing/app_b_an_py39/test_main.py
@@ -21,7 +21,7 @@ def test_read_item_bad_token():
assert response.json() == {"detail": "Invalid X-Token header"}
-def test_read_inexistent_item():
+def test_read_nonexistent_item():
response = client.get("/items/baz", headers={"X-Token": "coneofsilence"})
assert response.status_code == 404
assert response.json() == {"detail": "Item not found"}
diff --git a/docs_src/app_testing/app_b_py310/test_main.py b/docs_src/app_testing/app_b_py310/test_main.py
index 4e2b98e23..4e1c51ecc 100644
--- a/docs_src/app_testing/app_b_py310/test_main.py
+++ b/docs_src/app_testing/app_b_py310/test_main.py
@@ -21,7 +21,7 @@ def test_read_item_bad_token():
assert response.json() == {"detail": "Invalid X-Token header"}
-def test_read_inexistent_item():
+def test_read_nonexistent_item():
response = client.get("/items/baz", headers={"X-Token": "coneofsilence"})
assert response.status_code == 404
assert response.json() == {"detail": "Item not found"}
diff --git a/docs_src/custom_response/tutorial006c.py b/docs_src/custom_response/tutorial006c.py
index db87a9389..87c720364 100644
--- a/docs_src/custom_response/tutorial006c.py
+++ b/docs_src/custom_response/tutorial006c.py
@@ -6,4 +6,4 @@ app = FastAPI()
@app.get("/pydantic", response_class=RedirectResponse, status_code=302)
async def redirect_pydantic():
- return "https://pydantic-docs.helpmanual.io/"
+ return "https://docs.pydantic.dev/"
diff --git a/docs_src/dependencies/tutorial005_an.py b/docs_src/dependencies/tutorial005_an.py
index 6785099da..1d78c17a2 100644
--- a/docs_src/dependencies/tutorial005_an.py
+++ b/docs_src/dependencies/tutorial005_an.py
@@ -21,6 +21,6 @@ def query_or_cookie_extractor(
@app.get("/items/")
async def read_query(
- query_or_default: Annotated[str, Depends(query_or_cookie_extractor)]
+ 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
index 6c0aa0b36..5ccfc62bd 100644
--- a/docs_src/dependencies/tutorial005_an_py310.py
+++ b/docs_src/dependencies/tutorial005_an_py310.py
@@ -20,6 +20,6 @@ def query_or_cookie_extractor(
@app.get("/items/")
async def read_query(
- query_or_default: Annotated[str, Depends(query_or_cookie_extractor)]
+ 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
index e8887e162..d5dd8dca9 100644
--- a/docs_src/dependencies/tutorial005_an_py39.py
+++ b/docs_src/dependencies/tutorial005_an_py39.py
@@ -20,6 +20,6 @@ def query_or_cookie_extractor(
@app.get("/items/")
async def read_query(
- query_or_default: Annotated[str, Depends(query_or_cookie_extractor)]
+ query_or_default: Annotated[str, Depends(query_or_cookie_extractor)],
):
return {"q_or_cookie": query_or_default}
diff --git a/docs_src/dependencies/tutorial008c.py b/docs_src/dependencies/tutorial008c.py
new file mode 100644
index 000000000..4b99a5a31
--- /dev/null
+++ b/docs_src/dependencies/tutorial008c.py
@@ -0,0 +1,27 @@
+from fastapi import Depends, FastAPI, HTTPException
+
+app = FastAPI()
+
+
+class InternalError(Exception):
+ pass
+
+
+def get_username():
+ try:
+ yield "Rick"
+ except InternalError:
+ print("Oops, we didn't raise again, Britney 😱")
+
+
+@app.get("/items/{item_id}")
+def get_item(item_id: str, username: str = Depends(get_username)):
+ if item_id == "portal-gun":
+ raise InternalError(
+ f"The portal gun is too dangerous to be owned by {username}"
+ )
+ if item_id != "plumbus":
+ raise HTTPException(
+ status_code=404, detail="Item not found, there's only a plumbus here"
+ )
+ return item_id
diff --git a/docs_src/dependencies/tutorial008c_an.py b/docs_src/dependencies/tutorial008c_an.py
new file mode 100644
index 000000000..94f59f9aa
--- /dev/null
+++ b/docs_src/dependencies/tutorial008c_an.py
@@ -0,0 +1,28 @@
+from fastapi import Depends, FastAPI, HTTPException
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+class InternalError(Exception):
+ pass
+
+
+def get_username():
+ try:
+ yield "Rick"
+ except InternalError:
+ print("Oops, we didn't raise again, Britney 😱")
+
+
+@app.get("/items/{item_id}")
+def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
+ if item_id == "portal-gun":
+ raise InternalError(
+ f"The portal gun is too dangerous to be owned by {username}"
+ )
+ if item_id != "plumbus":
+ raise HTTPException(
+ status_code=404, detail="Item not found, there's only a plumbus here"
+ )
+ return item_id
diff --git a/docs_src/dependencies/tutorial008c_an_py39.py b/docs_src/dependencies/tutorial008c_an_py39.py
new file mode 100644
index 000000000..da92efa9c
--- /dev/null
+++ b/docs_src/dependencies/tutorial008c_an_py39.py
@@ -0,0 +1,29 @@
+from typing import Annotated
+
+from fastapi import Depends, FastAPI, HTTPException
+
+app = FastAPI()
+
+
+class InternalError(Exception):
+ pass
+
+
+def get_username():
+ try:
+ yield "Rick"
+ except InternalError:
+ print("Oops, we didn't raise again, Britney 😱")
+
+
+@app.get("/items/{item_id}")
+def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
+ if item_id == "portal-gun":
+ raise InternalError(
+ f"The portal gun is too dangerous to be owned by {username}"
+ )
+ if item_id != "plumbus":
+ raise HTTPException(
+ status_code=404, detail="Item not found, there's only a plumbus here"
+ )
+ return item_id
diff --git a/docs_src/dependencies/tutorial008d.py b/docs_src/dependencies/tutorial008d.py
new file mode 100644
index 000000000..93039343d
--- /dev/null
+++ b/docs_src/dependencies/tutorial008d.py
@@ -0,0 +1,28 @@
+from fastapi import Depends, FastAPI, HTTPException
+
+app = FastAPI()
+
+
+class InternalError(Exception):
+ pass
+
+
+def get_username():
+ try:
+ yield "Rick"
+ except InternalError:
+ print("We don't swallow the internal error here, we raise again 😎")
+ raise
+
+
+@app.get("/items/{item_id}")
+def get_item(item_id: str, username: str = Depends(get_username)):
+ if item_id == "portal-gun":
+ raise InternalError(
+ f"The portal gun is too dangerous to be owned by {username}"
+ )
+ if item_id != "plumbus":
+ raise HTTPException(
+ status_code=404, detail="Item not found, there's only a plumbus here"
+ )
+ return item_id
diff --git a/docs_src/dependencies/tutorial008d_an.py b/docs_src/dependencies/tutorial008d_an.py
new file mode 100644
index 000000000..c35424574
--- /dev/null
+++ b/docs_src/dependencies/tutorial008d_an.py
@@ -0,0 +1,29 @@
+from fastapi import Depends, FastAPI, HTTPException
+from typing_extensions import Annotated
+
+app = FastAPI()
+
+
+class InternalError(Exception):
+ pass
+
+
+def get_username():
+ try:
+ yield "Rick"
+ except InternalError:
+ print("We don't swallow the internal error here, we raise again 😎")
+ raise
+
+
+@app.get("/items/{item_id}")
+def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
+ if item_id == "portal-gun":
+ raise InternalError(
+ f"The portal gun is too dangerous to be owned by {username}"
+ )
+ if item_id != "plumbus":
+ raise HTTPException(
+ status_code=404, detail="Item not found, there's only a plumbus here"
+ )
+ return item_id
diff --git a/docs_src/dependencies/tutorial008d_an_py39.py b/docs_src/dependencies/tutorial008d_an_py39.py
new file mode 100644
index 000000000..99bd5cb91
--- /dev/null
+++ b/docs_src/dependencies/tutorial008d_an_py39.py
@@ -0,0 +1,30 @@
+from typing import Annotated
+
+from fastapi import Depends, FastAPI, HTTPException
+
+app = FastAPI()
+
+
+class InternalError(Exception):
+ pass
+
+
+def get_username():
+ try:
+ yield "Rick"
+ except InternalError:
+ print("We don't swallow the internal error here, we raise again 😎")
+ raise
+
+
+@app.get("/items/{item_id}")
+def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
+ if item_id == "portal-gun":
+ raise InternalError(
+ f"The portal gun is too dangerous to be owned by {username}"
+ )
+ if item_id != "plumbus":
+ raise HTTPException(
+ status_code=404, detail="Item not found, there's only a plumbus here"
+ )
+ return item_id
diff --git a/docs_src/generate_clients/tutorial004.js b/docs_src/generate_clients/tutorial004.js
index 18dc38267..fa222ba6c 100644
--- a/docs_src/generate_clients/tutorial004.js
+++ b/docs_src/generate_clients/tutorial004.js
@@ -1,29 +1,36 @@
-import * as fs from "fs";
+import * as fs from 'fs'
-const filePath = "./openapi.json";
+async function modifyOpenAPIFile(filePath) {
+ try {
+ const data = await fs.promises.readFile(filePath)
+ const openapiContent = JSON.parse(data)
-fs.readFile(filePath, (err, data) => {
- const openapiContent = JSON.parse(data);
- if (err) throw err;
-
- const paths = openapiContent.paths;
-
- Object.keys(paths).forEach((pathKey) => {
- const pathData = paths[pathKey];
- Object.keys(pathData).forEach((method) => {
- const operation = pathData[method];
- if (operation.tags && operation.tags.length > 0) {
- const tag = operation.tags[0];
- const operationId = operation.operationId;
- const toRemove = `${tag}-`;
- if (operationId.startsWith(toRemove)) {
- const newOperationId = operationId.substring(toRemove.length);
- operation.operationId = newOperationId;
+ const paths = openapiContent.paths
+ for (const pathKey of Object.keys(paths)) {
+ const pathData = paths[pathKey]
+ for (const method of Object.keys(pathData)) {
+ const operation = pathData[method]
+ if (operation.tags && operation.tags.length > 0) {
+ const tag = operation.tags[0]
+ const operationId = operation.operationId
+ const toRemove = `${tag}-`
+ if (operationId.startsWith(toRemove)) {
+ const newOperationId = operationId.substring(toRemove.length)
+ operation.operationId = newOperationId
+ }
}
}
- });
- });
- fs.writeFile(filePath, JSON.stringify(openapiContent, null, 2), (err) => {
- if (err) throw err;
- });
-});
+ }
+
+ await fs.promises.writeFile(
+ filePath,
+ JSON.stringify(openapiContent, null, 2),
+ )
+ console.log('File successfully modified')
+ } catch (err) {
+ console.error('Error:', err)
+ }
+}
+
+const filePath = './openapi.json'
+modifyOpenAPIFile(filePath)
diff --git a/docs_src/header_params/tutorial002.py b/docs_src/header_params/tutorial002.py
index 639ab1735..0a34f17cc 100644
--- a/docs_src/header_params/tutorial002.py
+++ b/docs_src/header_params/tutorial002.py
@@ -7,6 +7,6 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- strange_header: Union[str, None] = Header(default=None, convert_underscores=False)
+ strange_header: Union[str, None] = Header(default=None, convert_underscores=False),
):
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
index b340647b6..8a102749f 100644
--- a/docs_src/header_params/tutorial002_an_py310.py
+++ b/docs_src/header_params/tutorial002_an_py310.py
@@ -7,6 +7,6 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- strange_header: Annotated[str | None, Header(convert_underscores=False)] = None
+ strange_header: Annotated[str | None, Header(convert_underscores=False)] = None,
):
return {"strange_header": strange_header}
diff --git a/docs_src/header_params/tutorial002_py310.py b/docs_src/header_params/tutorial002_py310.py
index b7979b542..10d6716c6 100644
--- a/docs_src/header_params/tutorial002_py310.py
+++ b/docs_src/header_params/tutorial002_py310.py
@@ -5,6 +5,6 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- strange_header: str | None = Header(default=None, convert_underscores=False)
+ strange_header: str | None = Header(default=None, convert_underscores=False),
):
return {"strange_header": strange_header}
diff --git a/docs_src/query_params_str_validations/tutorial003.py b/docs_src/query_params_str_validations/tutorial003.py
index 73d2e08c8..7d4917373 100644
--- a/docs_src/query_params_str_validations/tutorial003.py
+++ b/docs_src/query_params_str_validations/tutorial003.py
@@ -7,7 +7,7 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- q: Union[str, None] = Query(default=None, min_length=3, max_length=50)
+ q: Union[str, None] = Query(default=None, min_length=3, max_length=50),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
diff --git a/docs_src/query_params_str_validations/tutorial003_an.py b/docs_src/query_params_str_validations/tutorial003_an.py
index a3665f6a8..0dd14086c 100644
--- a/docs_src/query_params_str_validations/tutorial003_an.py
+++ b/docs_src/query_params_str_validations/tutorial003_an.py
@@ -8,7 +8,7 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- q: Annotated[Union[str, None], Query(min_length=3, max_length=50)] = None
+ q: Annotated[Union[str, None], Query(min_length=3, max_length=50)] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
diff --git a/docs_src/query_params_str_validations/tutorial003_an_py310.py b/docs_src/query_params_str_validations/tutorial003_an_py310.py
index 836af04de..79a604b6c 100644
--- a/docs_src/query_params_str_validations/tutorial003_an_py310.py
+++ b/docs_src/query_params_str_validations/tutorial003_an_py310.py
@@ -7,7 +7,7 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- q: Annotated[str | None, Query(min_length=3, max_length=50)] = None
+ q: Annotated[str | None, Query(min_length=3, max_length=50)] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
diff --git a/docs_src/query_params_str_validations/tutorial003_an_py39.py b/docs_src/query_params_str_validations/tutorial003_an_py39.py
index 87a426839..3d6697793 100644
--- a/docs_src/query_params_str_validations/tutorial003_an_py39.py
+++ b/docs_src/query_params_str_validations/tutorial003_an_py39.py
@@ -7,7 +7,7 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- q: Annotated[Union[str, None], Query(min_length=3, max_length=50)] = None
+ q: Annotated[Union[str, None], Query(min_length=3, max_length=50)] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
diff --git a/docs_src/query_params_str_validations/tutorial007.py b/docs_src/query_params_str_validations/tutorial007.py
index cb836569e..27b649e14 100644
--- a/docs_src/query_params_str_validations/tutorial007.py
+++ b/docs_src/query_params_str_validations/tutorial007.py
@@ -7,7 +7,7 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- q: Union[str, None] = Query(default=None, title="Query string", min_length=3)
+ q: Union[str, None] = Query(default=None, title="Query string", min_length=3),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
diff --git a/docs_src/query_params_str_validations/tutorial007_an.py b/docs_src/query_params_str_validations/tutorial007_an.py
index 3bc85cc0c..4b3c8de4b 100644
--- a/docs_src/query_params_str_validations/tutorial007_an.py
+++ b/docs_src/query_params_str_validations/tutorial007_an.py
@@ -8,7 +8,7 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- q: Annotated[Union[str, None], Query(title="Query string", min_length=3)] = None
+ q: Annotated[Union[str, None], Query(title="Query string", min_length=3)] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
diff --git a/docs_src/query_params_str_validations/tutorial007_an_py310.py b/docs_src/query_params_str_validations/tutorial007_an_py310.py
index 5933911fd..ef18e500d 100644
--- a/docs_src/query_params_str_validations/tutorial007_an_py310.py
+++ b/docs_src/query_params_str_validations/tutorial007_an_py310.py
@@ -7,7 +7,7 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- q: Annotated[str | None, Query(title="Query string", min_length=3)] = None
+ q: Annotated[str | None, Query(title="Query string", min_length=3)] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
diff --git a/docs_src/query_params_str_validations/tutorial007_an_py39.py b/docs_src/query_params_str_validations/tutorial007_an_py39.py
index dafa1c5c9..8d7a82c46 100644
--- a/docs_src/query_params_str_validations/tutorial007_an_py39.py
+++ b/docs_src/query_params_str_validations/tutorial007_an_py39.py
@@ -7,7 +7,7 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- q: Annotated[Union[str, None], Query(title="Query string", min_length=3)] = None
+ q: Annotated[Union[str, None], Query(title="Query string", min_length=3)] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
diff --git a/docs_src/query_params_str_validations/tutorial007_py310.py b/docs_src/query_params_str_validations/tutorial007_py310.py
index e3e1ef2e0..c283576d5 100644
--- a/docs_src/query_params_str_validations/tutorial007_py310.py
+++ b/docs_src/query_params_str_validations/tutorial007_py310.py
@@ -5,7 +5,7 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- q: str | None = Query(default=None, title="Query string", min_length=3)
+ q: str | None = Query(default=None, title="Query string", min_length=3),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
diff --git a/docs_src/query_params_str_validations/tutorial014.py b/docs_src/query_params_str_validations/tutorial014.py
index 50e0a6c2b..779db1c80 100644
--- a/docs_src/query_params_str_validations/tutorial014.py
+++ b/docs_src/query_params_str_validations/tutorial014.py
@@ -7,7 +7,7 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- hidden_query: Union[str, None] = Query(default=None, include_in_schema=False)
+ hidden_query: Union[str, None] = Query(default=None, include_in_schema=False),
):
if hidden_query:
return {"hidden_query": hidden_query}
diff --git a/docs_src/query_params_str_validations/tutorial014_an.py b/docs_src/query_params_str_validations/tutorial014_an.py
index a9a9c4427..2eaa58540 100644
--- a/docs_src/query_params_str_validations/tutorial014_an.py
+++ b/docs_src/query_params_str_validations/tutorial014_an.py
@@ -8,7 +8,7 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- hidden_query: Annotated[Union[str, None], Query(include_in_schema=False)] = None
+ hidden_query: Annotated[Union[str, None], Query(include_in_schema=False)] = None,
):
if hidden_query:
return {"hidden_query": hidden_query}
diff --git a/docs_src/query_params_str_validations/tutorial014_an_py310.py b/docs_src/query_params_str_validations/tutorial014_an_py310.py
index 5fba54150..e728dbdb5 100644
--- a/docs_src/query_params_str_validations/tutorial014_an_py310.py
+++ b/docs_src/query_params_str_validations/tutorial014_an_py310.py
@@ -7,7 +7,7 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- hidden_query: Annotated[str | None, Query(include_in_schema=False)] = None
+ hidden_query: Annotated[str | None, Query(include_in_schema=False)] = None,
):
if hidden_query:
return {"hidden_query": hidden_query}
diff --git a/docs_src/query_params_str_validations/tutorial014_an_py39.py b/docs_src/query_params_str_validations/tutorial014_an_py39.py
index b07985210..aaf7703a5 100644
--- a/docs_src/query_params_str_validations/tutorial014_an_py39.py
+++ b/docs_src/query_params_str_validations/tutorial014_an_py39.py
@@ -7,7 +7,7 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- hidden_query: Annotated[Union[str, None], Query(include_in_schema=False)] = None
+ hidden_query: Annotated[Union[str, None], Query(include_in_schema=False)] = None,
):
if hidden_query:
return {"hidden_query": hidden_query}
diff --git a/docs_src/query_params_str_validations/tutorial014_py310.py b/docs_src/query_params_str_validations/tutorial014_py310.py
index 1b617efdd..97bb3386e 100644
--- a/docs_src/query_params_str_validations/tutorial014_py310.py
+++ b/docs_src/query_params_str_validations/tutorial014_py310.py
@@ -5,7 +5,7 @@ app = FastAPI()
@app.get("/items/")
async def read_items(
- hidden_query: str | None = Query(default=None, include_in_schema=False)
+ hidden_query: str | None = Query(default=None, include_in_schema=False),
):
if hidden_query:
return {"hidden_query": hidden_query}
diff --git a/docs_src/security/tutorial003_an.py b/docs_src/security/tutorial003_an.py
index 261cb4857..8fb40dd4a 100644
--- a/docs_src/security/tutorial003_an.py
+++ b/docs_src/security/tutorial003_an.py
@@ -68,7 +68,7 @@ async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
async def get_current_active_user(
- current_user: Annotated[User, Depends(get_current_user)]
+ current_user: Annotated[User, Depends(get_current_user)],
):
if current_user.disabled:
raise HTTPException(status_code=400, detail="Inactive user")
@@ -90,6 +90,6 @@ async def login(form_data: Annotated[OAuth2PasswordRequestForm, Depends()]):
@app.get("/users/me")
async def read_users_me(
- current_user: Annotated[User, Depends(get_current_active_user)]
+ 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
index a03f4f8bf..ced4a2fbc 100644
--- a/docs_src/security/tutorial003_an_py310.py
+++ b/docs_src/security/tutorial003_an_py310.py
@@ -67,7 +67,7 @@ async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
async def get_current_active_user(
- current_user: Annotated[User, Depends(get_current_user)]
+ current_user: Annotated[User, Depends(get_current_user)],
):
if current_user.disabled:
raise HTTPException(status_code=400, detail="Inactive user")
@@ -89,6 +89,6 @@ async def login(form_data: Annotated[OAuth2PasswordRequestForm, Depends()]):
@app.get("/users/me")
async def read_users_me(
- current_user: Annotated[User, Depends(get_current_active_user)]
+ 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
index 308dbe798..068a3933e 100644
--- a/docs_src/security/tutorial003_an_py39.py
+++ b/docs_src/security/tutorial003_an_py39.py
@@ -67,7 +67,7 @@ async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
async def get_current_active_user(
- current_user: Annotated[User, Depends(get_current_user)]
+ current_user: Annotated[User, Depends(get_current_user)],
):
if current_user.disabled:
raise HTTPException(status_code=400, detail="Inactive user")
@@ -89,6 +89,6 @@ async def login(form_data: Annotated[OAuth2PasswordRequestForm, Depends()]):
@app.get("/users/me")
async def read_users_me(
- current_user: Annotated[User, Depends(get_current_active_user)]
+ current_user: Annotated[User, Depends(get_current_active_user)],
):
return current_user
diff --git a/docs_src/security/tutorial004.py b/docs_src/security/tutorial004.py
index 044eec700..d0fbaa572 100644
--- a/docs_src/security/tutorial004.py
+++ b/docs_src/security/tutorial004.py
@@ -114,7 +114,7 @@ async def get_current_active_user(current_user: User = Depends(get_current_user)
@app.post("/token")
async def login_for_access_token(
- form_data: OAuth2PasswordRequestForm = Depends()
+ form_data: OAuth2PasswordRequestForm = Depends(),
) -> Token:
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
if not user:
diff --git a/docs_src/security/tutorial004_an.py b/docs_src/security/tutorial004_an.py
index c78e8496c..eebd36d64 100644
--- a/docs_src/security/tutorial004_an.py
+++ b/docs_src/security/tutorial004_an.py
@@ -108,7 +108,7 @@ async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
async def get_current_active_user(
- current_user: Annotated[User, Depends(get_current_user)]
+ current_user: Annotated[User, Depends(get_current_user)],
):
if current_user.disabled:
raise HTTPException(status_code=400, detail="Inactive user")
@@ -117,7 +117,7 @@ async def get_current_active_user(
@app.post("/token")
async def login_for_access_token(
- form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
+ form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
) -> Token:
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
if not user:
@@ -135,13 +135,13 @@ async def login_for_access_token(
@app.get("/users/me/", response_model=User)
async def read_users_me(
- current_user: Annotated[User, Depends(get_current_active_user)]
+ 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)]
+ 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
index 36dbc677e..4e50ada7c 100644
--- a/docs_src/security/tutorial004_an_py310.py
+++ b/docs_src/security/tutorial004_an_py310.py
@@ -107,7 +107,7 @@ async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
async def get_current_active_user(
- current_user: Annotated[User, Depends(get_current_user)]
+ current_user: Annotated[User, Depends(get_current_user)],
):
if current_user.disabled:
raise HTTPException(status_code=400, detail="Inactive user")
@@ -116,7 +116,7 @@ async def get_current_active_user(
@app.post("/token")
async def login_for_access_token(
- form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
+ form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
) -> Token:
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
if not user:
@@ -134,13 +134,13 @@ async def login_for_access_token(
@app.get("/users/me/", response_model=User)
async def read_users_me(
- current_user: Annotated[User, Depends(get_current_active_user)]
+ 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)]
+ 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
index 23fc04a72..eb49aaa67 100644
--- a/docs_src/security/tutorial004_an_py39.py
+++ b/docs_src/security/tutorial004_an_py39.py
@@ -107,7 +107,7 @@ async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
async def get_current_active_user(
- current_user: Annotated[User, Depends(get_current_user)]
+ current_user: Annotated[User, Depends(get_current_user)],
):
if current_user.disabled:
raise HTTPException(status_code=400, detail="Inactive user")
@@ -116,7 +116,7 @@ async def get_current_active_user(
@app.post("/token")
async def login_for_access_token(
- form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
+ form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
) -> Token:
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
if not user:
@@ -134,13 +134,13 @@ async def login_for_access_token(
@app.get("/users/me/", response_model=User)
async def read_users_me(
- current_user: Annotated[User, Depends(get_current_active_user)]
+ 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)]
+ current_user: Annotated[User, Depends(get_current_active_user)],
):
return [{"item_id": "Foo", "owner": current_user.username}]
diff --git a/docs_src/security/tutorial004_py310.py b/docs_src/security/tutorial004_py310.py
index 8363d45ab..5a905783d 100644
--- a/docs_src/security/tutorial004_py310.py
+++ b/docs_src/security/tutorial004_py310.py
@@ -113,7 +113,7 @@ async def get_current_active_user(current_user: User = Depends(get_current_user)
@app.post("/token")
async def login_for_access_token(
- form_data: OAuth2PasswordRequestForm = Depends()
+ form_data: OAuth2PasswordRequestForm = Depends(),
) -> Token:
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
if not user:
diff --git a/docs_src/security/tutorial005.py b/docs_src/security/tutorial005.py
index b16bf440a..d4a6975da 100644
--- a/docs_src/security/tutorial005.py
+++ b/docs_src/security/tutorial005.py
@@ -136,7 +136,7 @@ async def get_current_user(
async def get_current_active_user(
- current_user: User = Security(get_current_user, scopes=["me"])
+ current_user: User = Security(get_current_user, scopes=["me"]),
):
if current_user.disabled:
raise HTTPException(status_code=400, detail="Inactive user")
@@ -145,7 +145,7 @@ async def get_current_active_user(
@app.post("/token")
async def login_for_access_token(
- form_data: OAuth2PasswordRequestForm = Depends()
+ form_data: OAuth2PasswordRequestForm = Depends(),
) -> Token:
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
if not user:
@@ -165,7 +165,7 @@ async def read_users_me(current_user: User = Depends(get_current_active_user)):
@app.get("/users/me/items/")
async def read_own_items(
- current_user: User = Security(get_current_active_user, scopes=["items"])
+ current_user: User = Security(get_current_active_user, scopes=["items"]),
):
return [{"item_id": "Foo", "owner": current_user.username}]
diff --git a/docs_src/security/tutorial005_an.py b/docs_src/security/tutorial005_an.py
index 95e406b32..982daed2f 100644
--- a/docs_src/security/tutorial005_an.py
+++ b/docs_src/security/tutorial005_an.py
@@ -137,7 +137,7 @@ async def get_current_user(
async def get_current_active_user(
- current_user: Annotated[User, Security(get_current_user, scopes=["me"])]
+ current_user: Annotated[User, Security(get_current_user, scopes=["me"])],
):
if current_user.disabled:
raise HTTPException(status_code=400, detail="Inactive user")
@@ -146,7 +146,7 @@ async def get_current_active_user(
@app.post("/token")
async def login_for_access_token(
- form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
+ form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
) -> Token:
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
if not user:
@@ -161,14 +161,14 @@ async def login_for_access_token(
@app.get("/users/me/", response_model=User)
async def read_users_me(
- current_user: Annotated[User, Depends(get_current_active_user)]
+ 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"])]
+ current_user: Annotated[User, Security(get_current_active_user, scopes=["items"])],
):
return [{"item_id": "Foo", "owner": current_user.username}]
diff --git a/docs_src/security/tutorial005_an_py310.py b/docs_src/security/tutorial005_an_py310.py
index c6116a5ed..79aafbff1 100644
--- a/docs_src/security/tutorial005_an_py310.py
+++ b/docs_src/security/tutorial005_an_py310.py
@@ -136,7 +136,7 @@ async def get_current_user(
async def get_current_active_user(
- current_user: Annotated[User, Security(get_current_user, scopes=["me"])]
+ current_user: Annotated[User, Security(get_current_user, scopes=["me"])],
):
if current_user.disabled:
raise HTTPException(status_code=400, detail="Inactive user")
@@ -145,7 +145,7 @@ async def get_current_active_user(
@app.post("/token")
async def login_for_access_token(
- form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
+ form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
) -> Token:
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
if not user:
@@ -160,14 +160,14 @@ async def login_for_access_token(
@app.get("/users/me/", response_model=User)
async def read_users_me(
- current_user: Annotated[User, Depends(get_current_active_user)]
+ 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"])]
+ current_user: Annotated[User, Security(get_current_active_user, scopes=["items"])],
):
return [{"item_id": "Foo", "owner": current_user.username}]
diff --git a/docs_src/security/tutorial005_an_py39.py b/docs_src/security/tutorial005_an_py39.py
index af51c08b5..3bdab5507 100644
--- a/docs_src/security/tutorial005_an_py39.py
+++ b/docs_src/security/tutorial005_an_py39.py
@@ -136,7 +136,7 @@ async def get_current_user(
async def get_current_active_user(
- current_user: Annotated[User, Security(get_current_user, scopes=["me"])]
+ current_user: Annotated[User, Security(get_current_user, scopes=["me"])],
):
if current_user.disabled:
raise HTTPException(status_code=400, detail="Inactive user")
@@ -145,7 +145,7 @@ async def get_current_active_user(
@app.post("/token")
async def login_for_access_token(
- form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
+ form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
) -> Token:
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
if not user:
@@ -160,14 +160,14 @@ async def login_for_access_token(
@app.get("/users/me/", response_model=User)
async def read_users_me(
- current_user: Annotated[User, Depends(get_current_active_user)]
+ 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"])]
+ current_user: Annotated[User, Security(get_current_active_user, scopes=["items"])],
):
return [{"item_id": "Foo", "owner": current_user.username}]
diff --git a/docs_src/security/tutorial005_py310.py b/docs_src/security/tutorial005_py310.py
index 37a22c709..9f75aa0be 100644
--- a/docs_src/security/tutorial005_py310.py
+++ b/docs_src/security/tutorial005_py310.py
@@ -135,7 +135,7 @@ async def get_current_user(
async def get_current_active_user(
- current_user: User = Security(get_current_user, scopes=["me"])
+ current_user: User = Security(get_current_user, scopes=["me"]),
):
if current_user.disabled:
raise HTTPException(status_code=400, detail="Inactive user")
@@ -144,7 +144,7 @@ async def get_current_active_user(
@app.post("/token")
async def login_for_access_token(
- form_data: OAuth2PasswordRequestForm = Depends()
+ form_data: OAuth2PasswordRequestForm = Depends(),
) -> Token:
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
if not user:
@@ -164,7 +164,7 @@ async def read_users_me(current_user: User = Depends(get_current_active_user)):
@app.get("/users/me/items/")
async def read_own_items(
- current_user: User = Security(get_current_active_user, scopes=["items"])
+ current_user: User = Security(get_current_active_user, scopes=["items"]),
):
return [{"item_id": "Foo", "owner": current_user.username}]
diff --git a/docs_src/security/tutorial005_py39.py b/docs_src/security/tutorial005_py39.py
index c27580763..bac248932 100644
--- a/docs_src/security/tutorial005_py39.py
+++ b/docs_src/security/tutorial005_py39.py
@@ -136,7 +136,7 @@ async def get_current_user(
async def get_current_active_user(
- current_user: User = Security(get_current_user, scopes=["me"])
+ current_user: User = Security(get_current_user, scopes=["me"]),
):
if current_user.disabled:
raise HTTPException(status_code=400, detail="Inactive user")
@@ -145,7 +145,7 @@ async def get_current_active_user(
@app.post("/token")
async def login_for_access_token(
- form_data: OAuth2PasswordRequestForm = Depends()
+ form_data: OAuth2PasswordRequestForm = Depends(),
) -> Token:
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
if not user:
@@ -165,7 +165,7 @@ async def read_users_me(current_user: User = Depends(get_current_active_user)):
@app.get("/users/me/items/")
async def read_own_items(
- current_user: User = Security(get_current_active_user, scopes=["items"])
+ current_user: User = Security(get_current_active_user, scopes=["items"]),
):
return [{"item_id": "Foo", "owner": current_user.username}]
diff --git a/docs_src/security/tutorial007_an.py b/docs_src/security/tutorial007_an.py
index 9e9c3cd70..0d211dfde 100644
--- a/docs_src/security/tutorial007_an.py
+++ b/docs_src/security/tutorial007_an.py
@@ -10,7 +10,7 @@ security = HTTPBasic()
def get_current_username(
- credentials: Annotated[HTTPBasicCredentials, Depends(security)]
+ credentials: Annotated[HTTPBasicCredentials, Depends(security)],
):
current_username_bytes = credentials.username.encode("utf8")
correct_username_bytes = b"stanleyjobson"
diff --git a/docs_src/security/tutorial007_an_py39.py b/docs_src/security/tutorial007_an_py39.py
index 3d9ea2726..87ef98657 100644
--- a/docs_src/security/tutorial007_an_py39.py
+++ b/docs_src/security/tutorial007_an_py39.py
@@ -10,7 +10,7 @@ security = HTTPBasic()
def get_current_username(
- credentials: Annotated[HTTPBasicCredentials, Depends(security)]
+ credentials: Annotated[HTTPBasicCredentials, Depends(security)],
):
current_username_bytes = credentials.username.encode("utf8")
correct_username_bytes = b"stanleyjobson"
diff --git a/fastapi/__init__.py b/fastapi/__init__.py
index fedd8b419..234969256 100644
--- a/fastapi/__init__.py
+++ b/fastapi/__init__.py
@@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
-__version__ = "0.109.1"
+__version__ = "0.110.0"
from starlette import status as status
diff --git a/fastapi/applications.py b/fastapi/applications.py
index 597c60a56..d3edcc880 100644
--- a/fastapi/applications.py
+++ b/fastapi/applications.py
@@ -297,7 +297,7 @@ class FastAPI(Starlette):
browser tabs open). Or if you want to leave fixed the possible URLs.
If the servers `list` is not provided, or is an empty `list`, the
- default value would be a a `dict` with a `url` value of `/`.
+ default value would be a `dict` with a `url` value of `/`.
Each item in the `list` is a `dict` containing:
@@ -1019,7 +1019,7 @@ class FastAPI(Starlette):
oauth2_redirect_url = root_path + oauth2_redirect_url
return get_swagger_ui_html(
openapi_url=openapi_url,
- title=self.title + " - Swagger UI",
+ title=f"{self.title} - Swagger UI",
oauth2_redirect_url=oauth2_redirect_url,
init_oauth=self.swagger_ui_init_oauth,
swagger_ui_parameters=self.swagger_ui_parameters,
@@ -1043,7 +1043,7 @@ class FastAPI(Starlette):
root_path = req.scope.get("root_path", "").rstrip("/")
openapi_url = root_path + self.openapi_url
return get_redoc_html(
- openapi_url=openapi_url, title=self.title + " - ReDoc"
+ openapi_url=openapi_url, title=f"{self.title} - ReDoc"
)
self.add_route(self.redoc_url, redoc_html, include_in_schema=False)
diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py
index b73473484..02284b4ed 100644
--- a/fastapi/dependencies/utils.py
+++ b/fastapi/dependencies/utils.py
@@ -743,7 +743,7 @@ async def request_body_to_args(
results: List[Union[bytes, str]] = []
async def process_fn(
- fn: Callable[[], Coroutine[Any, Any, Any]]
+ fn: Callable[[], Coroutine[Any, Any, Any]],
) -> None:
result = await fn()
results.append(result) # noqa: B023
diff --git a/fastapi/encoders.py b/fastapi/encoders.py
index e50171393..431387f71 100644
--- a/fastapi/encoders.py
+++ b/fastapi/encoders.py
@@ -86,7 +86,7 @@ ENCODERS_BY_TYPE: Dict[Type[Any], Callable[[Any], Any]] = {
def generate_encoders_by_class_tuples(
- type_encoder_map: Dict[Any, Callable[[Any], Any]]
+ type_encoder_map: Dict[Any, Callable[[Any], Any]],
) -> Dict[Callable[[Any], Any], Tuple[Any, ...]]:
encoders_by_class_tuples: Dict[Callable[[Any], Any], Tuple[Any, ...]] = defaultdict(
tuple
diff --git a/fastapi/routing.py b/fastapi/routing.py
index acebabfca..23a32d15f 100644
--- a/fastapi/routing.py
+++ b/fastapi/routing.py
@@ -216,19 +216,14 @@ def get_request_handler(
actual_response_class = response_class
async def app(request: Request) -> Response:
- exception_to_reraise: Optional[Exception] = None
response: Union[Response, None] = None
- async with AsyncExitStack() as async_exit_stack:
- # TODO: remove this scope later, after a few releases
- # This scope fastapi_astack is no longer used by FastAPI, kept for
- # compatibility, just in case
- request.scope["fastapi_astack"] = async_exit_stack
+ async with AsyncExitStack() as file_stack:
try:
body: Any = None
if body_field:
if is_body_form:
body = await request.form()
- async_exit_stack.push_async_callback(body.close)
+ file_stack.push_async_callback(body.close)
else:
body_bytes = await request.body()
if body_bytes:
@@ -260,18 +255,17 @@ def get_request_handler(
],
body=e.doc,
)
- exception_to_reraise = validation_error
raise validation_error from e
- except HTTPException as e:
- exception_to_reraise = e
+ except HTTPException:
+ # If a middleware raises an HTTPException, it should be raised again
raise
except Exception as e:
http_error = HTTPException(
status_code=400, detail="There was an error parsing the body"
)
- exception_to_reraise = http_error
raise http_error from e
- try:
+ errors: List[Any] = []
+ async with AsyncExitStack() as async_exit_stack:
solved_result = await solve_dependencies(
request=request,
dependant=dependant,
@@ -280,59 +274,53 @@ def get_request_handler(
async_exit_stack=async_exit_stack,
)
values, errors, background_tasks, sub_response, _ = solved_result
- except Exception as e:
- exception_to_reraise = e
- raise e
+ if not errors:
+ raw_response = await run_endpoint_function(
+ dependant=dependant, values=values, is_coroutine=is_coroutine
+ )
+ if isinstance(raw_response, Response):
+ if raw_response.background is None:
+ raw_response.background = background_tasks
+ response = raw_response
+ else:
+ response_args: Dict[str, Any] = {"background": background_tasks}
+ # If status_code was set, use it, otherwise use the default from the
+ # response class, in the case of redirect it's 307
+ current_status_code = (
+ status_code if status_code else sub_response.status_code
+ )
+ if current_status_code is not None:
+ response_args["status_code"] = current_status_code
+ if sub_response.status_code:
+ response_args["status_code"] = sub_response.status_code
+ content = await serialize_response(
+ field=response_field,
+ response_content=raw_response,
+ include=response_model_include,
+ exclude=response_model_exclude,
+ by_alias=response_model_by_alias,
+ exclude_unset=response_model_exclude_unset,
+ exclude_defaults=response_model_exclude_defaults,
+ exclude_none=response_model_exclude_none,
+ is_coroutine=is_coroutine,
+ )
+ response = actual_response_class(content, **response_args)
+ if not is_body_allowed_for_status_code(response.status_code):
+ response.body = b""
+ response.headers.raw.extend(sub_response.headers.raw)
if errors:
validation_error = RequestValidationError(
_normalize_errors(errors), body=body
)
- exception_to_reraise = validation_error
raise validation_error
- else:
- try:
- raw_response = await run_endpoint_function(
- dependant=dependant, values=values, is_coroutine=is_coroutine
- )
- except Exception as e:
- exception_to_reraise = e
- raise e
- if isinstance(raw_response, Response):
- if raw_response.background is None:
- raw_response.background = background_tasks
- response = raw_response
- else:
- response_args: Dict[str, Any] = {"background": background_tasks}
- # If status_code was set, use it, otherwise use the default from the
- # response class, in the case of redirect it's 307
- current_status_code = (
- status_code if status_code else sub_response.status_code
- )
- if current_status_code is not None:
- response_args["status_code"] = current_status_code
- if sub_response.status_code:
- response_args["status_code"] = sub_response.status_code
- content = await serialize_response(
- field=response_field,
- response_content=raw_response,
- include=response_model_include,
- exclude=response_model_exclude,
- by_alias=response_model_by_alias,
- exclude_unset=response_model_exclude_unset,
- exclude_defaults=response_model_exclude_defaults,
- exclude_none=response_model_exclude_none,
- is_coroutine=is_coroutine,
- )
- response = actual_response_class(content, **response_args)
- if not is_body_allowed_for_status_code(response.status_code):
- response.body = b""
- response.headers.raw.extend(sub_response.headers.raw)
- # This exception was possibly handled by the dependency but it should
- # still bubble up so that the ServerErrorMiddleware can return a 500
- # or the ExceptionMiddleware can catch and handle any other exceptions
- if exception_to_reraise:
- raise exception_to_reraise
- assert response is not None, "An error occurred while generating the request"
+ if response is None:
+ raise FastAPIError(
+ "No response object was returned. There's a high chance that the "
+ "application code is raising an exception and a dependency with yield "
+ "has a block with a bare except, or a block with except Exception, "
+ "and is not raising the exception again. Read more about it in the "
+ "docs: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except"
+ )
return response
return app
diff --git a/fastapi/security/oauth2.py b/fastapi/security/oauth2.py
index be3e18cd8..d7ba44bce 100644
--- a/fastapi/security/oauth2.py
+++ b/fastapi/security/oauth2.py
@@ -54,7 +54,7 @@ class OAuth2PasswordRequestForm:
Note that for OAuth2 the scope `items:read` is a single scope in an opaque string.
You could have custom internal logic to separate it by colon caracters (`:`) or
similar, and get the two parts `items` and `read`. Many applications do that to
- group and organize permisions, you could do it as well in your application, just
+ group and organize permissions, you could do it as well in your application, just
know that that it is application specific, it's not part of the specification.
"""
@@ -196,7 +196,7 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm):
Note that for OAuth2 the scope `items:read` is a single scope in an opaque string.
You could have custom internal logic to separate it by colon caracters (`:`) or
similar, and get the two parts `items` and `read`. Many applications do that to
- group and organize permisions, you could do it as well in your application, just
+ group and organize permissions, you could do it as well in your application, just
know that that it is application specific, it's not part of the specification.
@@ -441,7 +441,7 @@ class OAuth2PasswordBearer(OAuth2):
bool,
Doc(
"""
- By default, if no HTTP Auhtorization header is provided, required for
+ By default, if no HTTP Authorization header is provided, required for
OAuth2 authentication, it will automatically cancel the request and
send the client an error.
@@ -543,7 +543,7 @@ class OAuth2AuthorizationCodeBearer(OAuth2):
bool,
Doc(
"""
- By default, if no HTTP Auhtorization header is provided, required for
+ By default, if no HTTP Authorization header is provided, required for
OAuth2 authentication, it will automatically cancel the request and
send the client an error.
diff --git a/fastapi/security/open_id_connect_url.py b/fastapi/security/open_id_connect_url.py
index c612b475d..1d255877d 100644
--- a/fastapi/security/open_id_connect_url.py
+++ b/fastapi/security/open_id_connect_url.py
@@ -49,7 +49,7 @@ class OpenIdConnect(SecurityBase):
bool,
Doc(
"""
- By default, if no HTTP Auhtorization header is provided, required for
+ By default, if no HTTP Authorization header is provided, required for
OpenID Connect authentication, it will automatically cancel the request
and send the client an error.
diff --git a/pyproject.toml b/pyproject.toml
index 31d9c59b3..c3801600a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -41,7 +41,7 @@ classifiers = [
"Topic :: Internet :: WWW/HTTP",
]
dependencies = [
- "starlette>=0.35.0,<0.36.0",
+ "starlette>=0.36.3,<0.37.0",
"pydantic>=1.7.4,!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0",
"typing-extensions>=4.8.0",
]
@@ -139,7 +139,7 @@ omit = [
"docs_src/response_model/tutorial003_04_py310.py",
]
-[tool.ruff]
+[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
@@ -152,10 +152,11 @@ select = [
ignore = [
"E501", # line too long, handled by black
"B008", # do not perform function calls in argument defaults
+ "C901", # too complex
"W191", # indentation contains tabs
]
-[tool.ruff.per-file-ignores]
+[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
"docs_src/dependencies/tutorial007.py" = ["F821"]
"docs_src/dependencies/tutorial008.py" = ["F821"]
@@ -188,9 +189,9 @@ ignore = [
"docs_src/dependencies/tutorial008b_an_py39.py" = ["B904"]
-[tool.ruff.isort]
+[tool.ruff.lint.isort]
known-third-party = ["fastapi", "pydantic", "starlette"]
-[tool.ruff.pyupgrade]
+[tool.ruff.lint.pyupgrade]
# Preserve types, even if a file imports `from __future__ import annotations`.
keep-runtime-typing = true
diff --git a/requirements-tests.txt b/requirements-tests.txt
index a5586c5ce..09ca9cb52 100644
--- a/requirements-tests.txt
+++ b/requirements-tests.txt
@@ -4,7 +4,7 @@ pydantic-settings >=2.0.0
pytest >=7.1.3,<8.0.0
coverage[toml] >= 6.5.0,< 8.0
mypy ==1.4.1
-ruff ==0.1.2
+ruff ==0.2.0
email_validator >=1.1.1,<3.0.0
dirty-equals ==0.6.0
# TODO: once removing databases from tutorial, upgrade SQLAlchemy
diff --git a/tests/test_dependency_contextmanager.py b/tests/test_dependency_contextmanager.py
index b07f9aa5b..008dab7bc 100644
--- a/tests/test_dependency_contextmanager.py
+++ b/tests/test_dependency_contextmanager.py
@@ -55,6 +55,7 @@ async def asyncgen_state_try(state: Dict[str, str] = Depends(get_state)):
yield state["/async_raise"]
except AsyncDependencyError:
errors.append("/async_raise")
+ raise
finally:
state["/async_raise"] = "asyncgen raise finalized"
@@ -65,6 +66,7 @@ def generator_state_try(state: Dict[str, str] = Depends(get_state)):
yield state["/sync_raise"]
except SyncDependencyError:
errors.append("/sync_raise")
+ raise
finally:
state["/sync_raise"] = "generator raise finalized"
diff --git a/tests/test_dependency_normal_exceptions.py b/tests/test_dependency_normal_exceptions.py
index 23c366d5d..326f8fd88 100644
--- a/tests/test_dependency_normal_exceptions.py
+++ b/tests/test_dependency_normal_exceptions.py
@@ -20,6 +20,7 @@ async def get_database():
fake_database.update(temp_database)
except HTTPException:
state["except"] = True
+ raise
finally:
state["finally"] = True
diff --git a/tests/test_param_include_in_schema.py b/tests/test_param_include_in_schema.py
index 26201e9e2..f461947c9 100644
--- a/tests/test_param_include_in_schema.py
+++ b/tests/test_param_include_in_schema.py
@@ -9,14 +9,14 @@ app = FastAPI()
@app.get("/hidden_cookie")
async def hidden_cookie(
- hidden_cookie: Optional[str] = Cookie(default=None, include_in_schema=False)
+ hidden_cookie: Optional[str] = Cookie(default=None, include_in_schema=False),
):
return {"hidden_cookie": hidden_cookie}
@app.get("/hidden_header")
async def hidden_header(
- hidden_header: Optional[str] = Header(default=None, include_in_schema=False)
+ hidden_header: Optional[str] = Header(default=None, include_in_schema=False),
):
return {"hidden_header": hidden_header}
@@ -28,7 +28,7 @@ async def hidden_path(hidden_path: str = Path(include_in_schema=False)):
@app.get("/hidden_query")
async def hidden_query(
- hidden_query: Optional[str] = Query(default=None, include_in_schema=False)
+ hidden_query: Optional[str] = Query(default=None, include_in_schema=False),
):
return {"hidden_query": hidden_query}
diff --git a/tests/test_regex_deprecated_body.py b/tests/test_regex_deprecated_body.py
index ca1ab514c..7afddd9ae 100644
--- a/tests/test_regex_deprecated_body.py
+++ b/tests/test_regex_deprecated_body.py
@@ -14,7 +14,7 @@ def get_client():
@app.post("/items/")
async def read_items(
- q: Annotated[str | None, Form(regex="^fixedquery$")] = None
+ q: Annotated[str | None, Form(regex="^fixedquery$")] = None,
):
if q:
return f"Hello {q}"
diff --git a/tests/test_regex_deprecated_params.py b/tests/test_regex_deprecated_params.py
index 79a653353..7190b543c 100644
--- a/tests/test_regex_deprecated_params.py
+++ b/tests/test_regex_deprecated_params.py
@@ -14,7 +14,7 @@ def get_client():
@app.get("/items/")
async def read_items(
- q: Annotated[str | None, Query(regex="^fixedquery$")] = None
+ q: Annotated[str | None, Query(regex="^fixedquery$")] = None,
):
if q:
return f"Hello {q}"
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006c.py b/tests/test_tutorial/test_custom_response/test_tutorial006c.py
index 51aa1833d..2675f2a93 100644
--- a/tests/test_tutorial/test_custom_response/test_tutorial006c.py
+++ b/tests/test_tutorial/test_custom_response/test_tutorial006c.py
@@ -8,7 +8,7 @@ client = TestClient(app)
def test_redirect_status_code():
response = client.get("/pydantic", follow_redirects=False)
assert response.status_code == 302
- assert response.headers["location"] == "https://pydantic-docs.helpmanual.io/"
+ assert response.headers["location"] == "https://docs.pydantic.dev/"
def test_openapi_schema():
diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008b_an_py39.py b/tests/test_tutorial/test_dependencies/test_tutorial008b_an_py39.py
index 7f51fc52a..7d24809a8 100644
--- a/tests/test_tutorial/test_dependencies/test_tutorial008b_an_py39.py
+++ b/tests/test_tutorial/test_dependencies/test_tutorial008b_an_py39.py
@@ -1,23 +1,33 @@
+import pytest
from fastapi.testclient import TestClient
-from docs_src.dependencies.tutorial008b_an import app
+from ...utils import needs_py39
-client = TestClient(app)
+@pytest.fixture(name="client")
+def get_client():
+ from docs_src.dependencies.tutorial008b_an_py39 import app
-def test_get_no_item():
+ client = TestClient(app)
+ return client
+
+
+@needs_py39
+def test_get_no_item(client: TestClient):
response = client.get("/items/foo")
assert response.status_code == 404, response.text
assert response.json() == {"detail": "Item not found"}
-def test_owner_error():
+@needs_py39
+def test_owner_error(client: TestClient):
response = client.get("/items/plumbus")
assert response.status_code == 400, response.text
assert response.json() == {"detail": "Owner error: Rick"}
-def test_get_item():
+@needs_py39
+def test_get_item(client: TestClient):
response = client.get("/items/portal-gun")
assert response.status_code == 200, response.text
assert response.json() == {"description": "Gun to create portals", "owner": "Rick"}
diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008c.py b/tests/test_tutorial/test_dependencies/test_tutorial008c.py
new file mode 100644
index 000000000..27be8895a
--- /dev/null
+++ b/tests/test_tutorial/test_dependencies/test_tutorial008c.py
@@ -0,0 +1,38 @@
+import pytest
+from fastapi.exceptions import FastAPIError
+from fastapi.testclient import TestClient
+
+
+@pytest.fixture(name="client")
+def get_client():
+ from docs_src.dependencies.tutorial008c import app
+
+ client = TestClient(app)
+ return client
+
+
+def test_get_no_item(client: TestClient):
+ response = client.get("/items/foo")
+ assert response.status_code == 404, response.text
+ assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
+
+
+def test_get(client: TestClient):
+ response = client.get("/items/plumbus")
+ assert response.status_code == 200, response.text
+ assert response.json() == "plumbus"
+
+
+def test_fastapi_error(client: TestClient):
+ with pytest.raises(FastAPIError) as exc_info:
+ client.get("/items/portal-gun")
+ assert "No response object was returned" in exc_info.value.args[0]
+
+
+def test_internal_server_error():
+ from docs_src.dependencies.tutorial008c import app
+
+ client = TestClient(app, raise_server_exceptions=False)
+ response = client.get("/items/portal-gun")
+ assert response.status_code == 500, response.text
+ assert response.text == "Internal Server Error"
diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008c_an.py b/tests/test_tutorial/test_dependencies/test_tutorial008c_an.py
new file mode 100644
index 000000000..10fa1ab50
--- /dev/null
+++ b/tests/test_tutorial/test_dependencies/test_tutorial008c_an.py
@@ -0,0 +1,38 @@
+import pytest
+from fastapi.exceptions import FastAPIError
+from fastapi.testclient import TestClient
+
+
+@pytest.fixture(name="client")
+def get_client():
+ from docs_src.dependencies.tutorial008c_an import app
+
+ client = TestClient(app)
+ return client
+
+
+def test_get_no_item(client: TestClient):
+ response = client.get("/items/foo")
+ assert response.status_code == 404, response.text
+ assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
+
+
+def test_get(client: TestClient):
+ response = client.get("/items/plumbus")
+ assert response.status_code == 200, response.text
+ assert response.json() == "plumbus"
+
+
+def test_fastapi_error(client: TestClient):
+ with pytest.raises(FastAPIError) as exc_info:
+ client.get("/items/portal-gun")
+ assert "No response object was returned" in exc_info.value.args[0]
+
+
+def test_internal_server_error():
+ from docs_src.dependencies.tutorial008c_an import app
+
+ client = TestClient(app, raise_server_exceptions=False)
+ response = client.get("/items/portal-gun")
+ assert response.status_code == 500, response.text
+ assert response.text == "Internal Server Error"
diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008c_an_py39.py b/tests/test_tutorial/test_dependencies/test_tutorial008c_an_py39.py
new file mode 100644
index 000000000..6c3acff50
--- /dev/null
+++ b/tests/test_tutorial/test_dependencies/test_tutorial008c_an_py39.py
@@ -0,0 +1,44 @@
+import pytest
+from fastapi.exceptions import FastAPIError
+from fastapi.testclient import TestClient
+
+from ...utils import needs_py39
+
+
+@pytest.fixture(name="client")
+def get_client():
+ from docs_src.dependencies.tutorial008c_an_py39 import app
+
+ client = TestClient(app)
+ return client
+
+
+@needs_py39
+def test_get_no_item(client: TestClient):
+ response = client.get("/items/foo")
+ assert response.status_code == 404, response.text
+ assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
+
+
+@needs_py39
+def test_get(client: TestClient):
+ response = client.get("/items/plumbus")
+ assert response.status_code == 200, response.text
+ assert response.json() == "plumbus"
+
+
+@needs_py39
+def test_fastapi_error(client: TestClient):
+ with pytest.raises(FastAPIError) as exc_info:
+ client.get("/items/portal-gun")
+ assert "No response object was returned" in exc_info.value.args[0]
+
+
+@needs_py39
+def test_internal_server_error():
+ from docs_src.dependencies.tutorial008c_an_py39 import app
+
+ client = TestClient(app, raise_server_exceptions=False)
+ response = client.get("/items/portal-gun")
+ assert response.status_code == 500, response.text
+ assert response.text == "Internal Server Error"
diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008d.py b/tests/test_tutorial/test_dependencies/test_tutorial008d.py
new file mode 100644
index 000000000..043496112
--- /dev/null
+++ b/tests/test_tutorial/test_dependencies/test_tutorial008d.py
@@ -0,0 +1,41 @@
+import pytest
+from fastapi.testclient import TestClient
+
+
+@pytest.fixture(name="client")
+def get_client():
+ from docs_src.dependencies.tutorial008d import app
+
+ client = TestClient(app)
+ return client
+
+
+def test_get_no_item(client: TestClient):
+ response = client.get("/items/foo")
+ assert response.status_code == 404, response.text
+ assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
+
+
+def test_get(client: TestClient):
+ response = client.get("/items/plumbus")
+ assert response.status_code == 200, response.text
+ assert response.json() == "plumbus"
+
+
+def test_internal_error(client: TestClient):
+ from docs_src.dependencies.tutorial008d import InternalError
+
+ with pytest.raises(InternalError) as exc_info:
+ client.get("/items/portal-gun")
+ assert (
+ exc_info.value.args[0] == "The portal gun is too dangerous to be owned by Rick"
+ )
+
+
+def test_internal_server_error():
+ from docs_src.dependencies.tutorial008d import app
+
+ client = TestClient(app, raise_server_exceptions=False)
+ response = client.get("/items/portal-gun")
+ assert response.status_code == 500, response.text
+ assert response.text == "Internal Server Error"
diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008d_an.py b/tests/test_tutorial/test_dependencies/test_tutorial008d_an.py
new file mode 100644
index 000000000..f29d8cdbe
--- /dev/null
+++ b/tests/test_tutorial/test_dependencies/test_tutorial008d_an.py
@@ -0,0 +1,41 @@
+import pytest
+from fastapi.testclient import TestClient
+
+
+@pytest.fixture(name="client")
+def get_client():
+ from docs_src.dependencies.tutorial008d_an import app
+
+ client = TestClient(app)
+ return client
+
+
+def test_get_no_item(client: TestClient):
+ response = client.get("/items/foo")
+ assert response.status_code == 404, response.text
+ assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
+
+
+def test_get(client: TestClient):
+ response = client.get("/items/plumbus")
+ assert response.status_code == 200, response.text
+ assert response.json() == "plumbus"
+
+
+def test_internal_error(client: TestClient):
+ from docs_src.dependencies.tutorial008d_an import InternalError
+
+ with pytest.raises(InternalError) as exc_info:
+ client.get("/items/portal-gun")
+ assert (
+ exc_info.value.args[0] == "The portal gun is too dangerous to be owned by Rick"
+ )
+
+
+def test_internal_server_error():
+ from docs_src.dependencies.tutorial008d_an import app
+
+ client = TestClient(app, raise_server_exceptions=False)
+ response = client.get("/items/portal-gun")
+ assert response.status_code == 500, response.text
+ assert response.text == "Internal Server Error"
diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008d_an_py39.py b/tests/test_tutorial/test_dependencies/test_tutorial008d_an_py39.py
new file mode 100644
index 000000000..0a585f4ad
--- /dev/null
+++ b/tests/test_tutorial/test_dependencies/test_tutorial008d_an_py39.py
@@ -0,0 +1,47 @@
+import pytest
+from fastapi.testclient import TestClient
+
+from ...utils import needs_py39
+
+
+@pytest.fixture(name="client")
+def get_client():
+ from docs_src.dependencies.tutorial008d_an_py39 import app
+
+ client = TestClient(app)
+ return client
+
+
+@needs_py39
+def test_get_no_item(client: TestClient):
+ response = client.get("/items/foo")
+ assert response.status_code == 404, response.text
+ assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
+
+
+@needs_py39
+def test_get(client: TestClient):
+ response = client.get("/items/plumbus")
+ assert response.status_code == 200, response.text
+ assert response.json() == "plumbus"
+
+
+@needs_py39
+def test_internal_error(client: TestClient):
+ from docs_src.dependencies.tutorial008d_an_py39 import InternalError
+
+ with pytest.raises(InternalError) as exc_info:
+ client.get("/items/portal-gun")
+ assert (
+ exc_info.value.args[0] == "The portal gun is too dangerous to be owned by Rick"
+ )
+
+
+@needs_py39
+def test_internal_server_error():
+ from docs_src.dependencies.tutorial008d_an_py39 import app
+
+ client = TestClient(app, raise_server_exceptions=False)
+ response = client.get("/items/portal-gun")
+ assert response.status_code == 500, response.text
+ assert response.text == "Internal Server Error"
diff --git a/tests/test_tutorial/test_security/test_tutorial005.py b/tests/test_tutorial/test_security/test_tutorial005.py
index c669c306d..2e580dbb3 100644
--- a/tests/test_tutorial/test_security/test_tutorial005.py
+++ b/tests/test_tutorial/test_security/test_tutorial005.py
@@ -128,7 +128,7 @@ def test_token_no_scope():
assert response.headers["WWW-Authenticate"] == 'Bearer scope="me"'
-def test_token_inexistent_user():
+def test_token_nonexistent_user():
response = client.get(
"/users/me",
headers={
diff --git a/tests/test_tutorial/test_security/test_tutorial005_an.py b/tests/test_tutorial/test_security/test_tutorial005_an.py
index aaab04f78..04c7d60bc 100644
--- a/tests/test_tutorial/test_security/test_tutorial005_an.py
+++ b/tests/test_tutorial/test_security/test_tutorial005_an.py
@@ -128,7 +128,7 @@ def test_token_no_scope():
assert response.headers["WWW-Authenticate"] == 'Bearer scope="me"'
-def test_token_inexistent_user():
+def test_token_nonexistent_user():
response = client.get(
"/users/me",
headers={
diff --git a/tests/test_tutorial/test_security/test_tutorial005_an_py310.py b/tests/test_tutorial/test_security/test_tutorial005_an_py310.py
index 243d0773c..9c7f83ed2 100644
--- a/tests/test_tutorial/test_security/test_tutorial005_an_py310.py
+++ b/tests/test_tutorial/test_security/test_tutorial005_an_py310.py
@@ -151,7 +151,7 @@ def test_token_no_scope(client: TestClient):
@needs_py310
-def test_token_inexistent_user(client: TestClient):
+def test_token_nonexistent_user(client: TestClient):
response = client.get(
"/users/me",
headers={
diff --git a/tests/test_tutorial/test_security/test_tutorial005_an_py39.py b/tests/test_tutorial/test_security/test_tutorial005_an_py39.py
index 17a3f9aa2..04cc1b014 100644
--- a/tests/test_tutorial/test_security/test_tutorial005_an_py39.py
+++ b/tests/test_tutorial/test_security/test_tutorial005_an_py39.py
@@ -151,7 +151,7 @@ def test_token_no_scope(client: TestClient):
@needs_py39
-def test_token_inexistent_user(client: TestClient):
+def test_token_nonexistent_user(client: TestClient):
response = client.get(
"/users/me",
headers={
diff --git a/tests/test_tutorial/test_security/test_tutorial005_py310.py b/tests/test_tutorial/test_security/test_tutorial005_py310.py
index 06455cd63..98c60c1c2 100644
--- a/tests/test_tutorial/test_security/test_tutorial005_py310.py
+++ b/tests/test_tutorial/test_security/test_tutorial005_py310.py
@@ -151,7 +151,7 @@ def test_token_no_scope(client: TestClient):
@needs_py310
-def test_token_inexistent_user(client: TestClient):
+def test_token_nonexistent_user(client: TestClient):
response = client.get(
"/users/me",
headers={
diff --git a/tests/test_tutorial/test_security/test_tutorial005_py39.py b/tests/test_tutorial/test_security/test_tutorial005_py39.py
index 9455bfb4e..cd2157d54 100644
--- a/tests/test_tutorial/test_security/test_tutorial005_py39.py
+++ b/tests/test_tutorial/test_security/test_tutorial005_py39.py
@@ -151,7 +151,7 @@ def test_token_no_scope(client: TestClient):
@needs_py39
-def test_token_inexistent_user(client: TestClient):
+def test_token_nonexistent_user(client: TestClient):
response = client.get(
"/users/me",
headers={
diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases.py b/tests/test_tutorial/test_sql_databases/test_sql_databases.py
index 03e747433..e3e2b36a8 100644
--- a/tests/test_tutorial/test_sql_databases/test_sql_databases.py
+++ b/tests/test_tutorial/test_sql_databases/test_sql_databases.py
@@ -54,7 +54,7 @@ def test_get_user(client):
# TODO: pv2 add version with Pydantic v2
@needs_pydanticv1
-def test_inexistent_user(client):
+def test_nonexistent_user(client):
response = client.get("/users/999")
assert response.status_code == 404, response.text
diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware.py b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware.py
index a503ef2a6..73b97e09d 100644
--- a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware.py
+++ b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware.py
@@ -50,7 +50,7 @@ def test_get_user(client):
# TODO: pv2 add version with Pydantic v2
@needs_pydanticv1
-def test_inexistent_user(client):
+def test_nonexistent_user(client):
response = client.get("/users/999")
assert response.status_code == 404, response.text
diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py310.py b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py310.py
index d54cc6552..a078f012a 100644
--- a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py310.py
+++ b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py310.py
@@ -58,7 +58,7 @@ def test_get_user(client):
@needs_py310
# TODO: pv2 add version with Pydantic v2
@needs_pydanticv1
-def test_inexistent_user(client):
+def test_nonexistent_user(client):
response = client.get("/users/999")
assert response.status_code == 404, response.text
diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py39.py b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py39.py
index 4e43995e6..a5da07ac6 100644
--- a/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py39.py
+++ b/tests/test_tutorial/test_sql_databases/test_sql_databases_middleware_py39.py
@@ -58,7 +58,7 @@ def test_get_user(client):
@needs_py39
# TODO: pv2 add version with Pydantic v2
@needs_pydanticv1
-def test_inexistent_user(client):
+def test_nonexistent_user(client):
response = client.get("/users/999")
assert response.status_code == 404, response.text
diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases_py310.py b/tests/test_tutorial/test_sql_databases/test_sql_databases_py310.py
index b89b8b031..5a9106598 100644
--- a/tests/test_tutorial/test_sql_databases/test_sql_databases_py310.py
+++ b/tests/test_tutorial/test_sql_databases/test_sql_databases_py310.py
@@ -57,7 +57,7 @@ def test_get_user(client):
@needs_py310
# TODO: pv2 add version with Pydantic v2
@needs_pydanticv1
-def test_inexistent_user(client):
+def test_nonexistent_user(client):
response = client.get("/users/999")
assert response.status_code == 404, response.text
diff --git a/tests/test_tutorial/test_sql_databases/test_sql_databases_py39.py b/tests/test_tutorial/test_sql_databases/test_sql_databases_py39.py
index 13351bc81..a354ba905 100644
--- a/tests/test_tutorial/test_sql_databases/test_sql_databases_py39.py
+++ b/tests/test_tutorial/test_sql_databases/test_sql_databases_py39.py
@@ -57,7 +57,7 @@ def test_get_user(client):
@needs_py39
# TODO: pv2 add version with Pydantic v2
@needs_pydanticv1
-def test_inexistent_user(client):
+def test_nonexistent_user(client):
response = client.get("/users/999")
assert response.status_code == 404, response.text
diff --git a/tests/test_tutorial/test_testing/test_main_b.py b/tests/test_tutorial/test_testing/test_main_b.py
index fc1a832f9..1e1836f5b 100644
--- a/tests/test_tutorial/test_testing/test_main_b.py
+++ b/tests/test_tutorial/test_testing/test_main_b.py
@@ -5,6 +5,6 @@ def test_app():
test_main.test_create_existing_item()
test_main.test_create_item()
test_main.test_create_item_bad_token()
- test_main.test_read_inexistent_item()
+ test_main.test_read_nonexistent_item()
test_main.test_read_item()
test_main.test_read_item_bad_token()
diff --git a/tests/test_tutorial/test_testing/test_main_b_an.py b/tests/test_tutorial/test_testing/test_main_b_an.py
index b64c5f710..e53fc3224 100644
--- a/tests/test_tutorial/test_testing/test_main_b_an.py
+++ b/tests/test_tutorial/test_testing/test_main_b_an.py
@@ -5,6 +5,6 @@ def test_app():
test_main.test_create_existing_item()
test_main.test_create_item()
test_main.test_create_item_bad_token()
- test_main.test_read_inexistent_item()
+ test_main.test_read_nonexistent_item()
test_main.test_read_item()
test_main.test_read_item_bad_token()
diff --git a/tests/test_tutorial/test_testing/test_main_b_an_py310.py b/tests/test_tutorial/test_testing/test_main_b_an_py310.py
index 194700b6d..c974e5dc1 100644
--- a/tests/test_tutorial/test_testing/test_main_b_an_py310.py
+++ b/tests/test_tutorial/test_testing/test_main_b_an_py310.py
@@ -8,6 +8,6 @@ def test_app():
test_main.test_create_existing_item()
test_main.test_create_item()
test_main.test_create_item_bad_token()
- test_main.test_read_inexistent_item()
+ test_main.test_read_nonexistent_item()
test_main.test_read_item()
test_main.test_read_item_bad_token()
diff --git a/tests/test_tutorial/test_testing/test_main_b_an_py39.py b/tests/test_tutorial/test_testing/test_main_b_an_py39.py
index 2f8a13623..71f99726c 100644
--- a/tests/test_tutorial/test_testing/test_main_b_an_py39.py
+++ b/tests/test_tutorial/test_testing/test_main_b_an_py39.py
@@ -8,6 +8,6 @@ def test_app():
test_main.test_create_existing_item()
test_main.test_create_item()
test_main.test_create_item_bad_token()
- test_main.test_read_inexistent_item()
+ test_main.test_read_nonexistent_item()
test_main.test_read_item()
test_main.test_read_item_bad_token()
diff --git a/tests/test_tutorial/test_testing/test_main_b_py310.py b/tests/test_tutorial/test_testing/test_main_b_py310.py
index a504ed234..e30cdc073 100644
--- a/tests/test_tutorial/test_testing/test_main_b_py310.py
+++ b/tests/test_tutorial/test_testing/test_main_b_py310.py
@@ -8,6 +8,6 @@ def test_app():
test_main.test_create_existing_item()
test_main.test_create_item()
test_main.test_create_item_bad_token()
- test_main.test_read_inexistent_item()
+ test_main.test_read_nonexistent_item()
test_main.test_read_item()
test_main.test_read_item_bad_token()