Browse Source
* Update all * Reflect latest changes in `docs/en/docs/tutorial/security/oauth2-jwt.md`pull/14911/head
committed by
GitHub
90 changed files with 549 additions and 620 deletions
@ -0,0 +1,61 @@ |
|||||
|
# Продвинутые типы Python { #advanced-python-types } |
||||
|
|
||||
|
Ниже несколько дополнительных идей, которые могут быть полезны при работе с типами Python. |
||||
|
|
||||
|
## Использование `Union` или `Optional` { #using-union-or-optional } |
||||
|
|
||||
|
Если по какой-то причине ваш код не может использовать `|`, например, если это не аннотация типов, а что-то вроде `response_model=`, вместо вертикальной черты (`|`) можно использовать `Union` из `typing`. |
||||
|
|
||||
|
Например, вы можете объявить, что значение может быть `str` или `None`: |
||||
|
|
||||
|
```python |
||||
|
from typing import Union |
||||
|
|
||||
|
|
||||
|
def say_hi(name: Union[str, None]): |
||||
|
print(f"Hi {name}!") |
||||
|
``` |
||||
|
|
||||
|
В `typing` также есть сокращение, чтобы объявить, что значение может быть `None`, — `Optional`. |
||||
|
|
||||
|
Вот совет с моей очень субъективной точки зрения: |
||||
|
|
||||
|
- 🚨 Избегайте использования `Optional[SomeType]` |
||||
|
- Вместо этого ✨ используйте **`Union[SomeType, None]`** ✨. |
||||
|
|
||||
|
Оба варианта эквивалентны и под капотом это одно и то же, но я бы рекомендовал `Union` вместо `Optional`, потому что слово «optional» может наводить на мысль, что значение необязательное, тогда как на самом деле это означает «значение может быть `None`», даже если оно не является необязательным и по-прежнему требуется. |
||||
|
|
||||
|
По-моему, `Union[SomeType, None]` более явно передаёт смысл. |
||||
|
|
||||
|
Речь только о словах и названиях. Но эти слова могут влиять на то, как вы и ваша команда думаете о коде. |
||||
|
|
||||
|
В качестве примера возьмём такую функцию: |
||||
|
|
||||
|
```python |
||||
|
from typing import Optional |
||||
|
|
||||
|
|
||||
|
def say_hi(name: Optional[str]): |
||||
|
print(f"Hey {name}!") |
||||
|
``` |
||||
|
|
||||
|
Параметр `name` объявлен как `Optional[str]`, но он не является необязательным: вы не можете вызвать функцию без этого параметра: |
||||
|
|
||||
|
```Python |
||||
|
say_hi() # О нет, это вызывает ошибку! 😱 |
||||
|
``` |
||||
|
|
||||
|
Параметр `name` по-прежнему обязателен (не «optional»), так как у него нет значения по умолчанию. При этом `name` принимает `None` в качестве значения: |
||||
|
|
||||
|
```Python |
||||
|
say_hi(name=None) # Это работает, None допустим 🎉 |
||||
|
``` |
||||
|
|
||||
|
Хорошая новость: в большинстве случаев вы сможете просто использовать `|` для объявления объединений типов: |
||||
|
|
||||
|
```python |
||||
|
def say_hi(name: str | None): |
||||
|
print(f"Hey {name}!") |
||||
|
``` |
||||
|
|
||||
|
Так что обычно вам не о чем переживать из‑за названий вроде `Optional` и `Union`. 😎 |
||||
@ -54,7 +54,7 @@ $ pip install "fastapi[all]" |
|||||
|
|
||||
Вы можете использовать все те же возможности валидации и инструменты, что и для Pydantic‑моделей, например разные типы данных и дополнительную валидацию через `Field()`. |
Вы можете использовать все те же возможности валидации и инструменты, что и для Pydantic‑моделей, например разные типы данных и дополнительную валидацию через `Field()`. |
||||
|
|
||||
{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *} |
{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} |
||||
|
|
||||
/// tip | Совет |
/// tip | Совет |
||||
|
|
||||
@ -70,7 +70,7 @@ $ pip install "fastapi[all]" |
|||||
|
|
||||
Затем вы можете использовать новый объект `settings` в вашем приложении: |
Затем вы можете использовать новый объект `settings` в вашем приложении: |
||||
|
|
||||
{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *} |
{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *} |
||||
|
|
||||
### Запуск сервера { #run-the-server } |
### Запуск сервера { #run-the-server } |
||||
|
|
||||
@ -104,11 +104,11 @@ $ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" fastapi run main.p |
|||||
|
|
||||
Например, у вас может быть файл `config.py` со следующим содержимым: |
Например, у вас может быть файл `config.py` со следующим содержимым: |
||||
|
|
||||
{* ../../docs_src/settings/app01_py39/config.py *} |
{* ../../docs_src/settings/app01_py310/config.py *} |
||||
|
|
||||
А затем использовать его в файле `main.py`: |
А затем использовать его в файле `main.py`: |
||||
|
|
||||
{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *} |
{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *} |
||||
|
|
||||
/// tip | Совет |
/// tip | Совет |
||||
|
|
||||
@ -126,7 +126,7 @@ $ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" fastapi run main.p |
|||||
|
|
||||
Продолжая предыдущий пример, ваш файл `config.py` может выглядеть так: |
Продолжая предыдущий пример, ваш файл `config.py` может выглядеть так: |
||||
|
|
||||
{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *} |
{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} |
||||
|
|
||||
Обратите внимание, что теперь мы не создаем экземпляр по умолчанию `settings = Settings()`. |
Обратите внимание, что теперь мы не создаем экземпляр по умолчанию `settings = Settings()`. |
||||
|
|
||||
@ -134,7 +134,7 @@ $ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" fastapi run main.p |
|||||
|
|
||||
Теперь мы создаем зависимость, которая возвращает новый `config.Settings()`. |
Теперь мы создаем зависимость, которая возвращает новый `config.Settings()`. |
||||
|
|
||||
{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *} |
{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *} |
||||
|
|
||||
/// tip | Совет |
/// tip | Совет |
||||
|
|
||||
@ -146,13 +146,13 @@ $ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" fastapi run main.p |
|||||
|
|
||||
Затем мы можем запросить ее в *функции-обработчике пути* как зависимость и использовать там, где нужно. |
Затем мы можем запросить ее в *функции-обработчике пути* как зависимость и использовать там, где нужно. |
||||
|
|
||||
{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *} |
{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} |
||||
|
|
||||
### Настройки и тестирование { #settings-and-testing } |
### Настройки и тестирование { #settings-and-testing } |
||||
|
|
||||
Далее будет очень просто предоставить другой объект настроек во время тестирования, создав переопределение зависимости для `get_settings`: |
Далее будет очень просто предоставить другой объект настроек во время тестирования, создав переопределение зависимости для `get_settings`: |
||||
|
|
||||
{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *} |
{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} |
||||
|
|
||||
В переопределении зависимости мы задаем новое значение `admin_email` при создании нового объекта `Settings`, а затем возвращаем этот новый объект. |
В переопределении зависимости мы задаем новое значение `admin_email` при создании нового объекта `Settings`, а затем возвращаем этот новый объект. |
||||
|
|
||||
@ -193,7 +193,7 @@ APP_NAME="ChimichangApp" |
|||||
|
|
||||
Затем обновите ваш `config.py` так: |
Затем обновите ваш `config.py` так: |
||||
|
|
||||
{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *} |
{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *} |
||||
|
|
||||
/// tip | Совет |
/// tip | Совет |
||||
|
|
||||
@ -226,7 +226,7 @@ def get_settings(): |
|||||
|
|
||||
Но так как мы используем декоратор `@lru_cache` сверху, объект `Settings` будет создан только один раз — при первом вызове. ✔️ |
Но так как мы используем декоратор `@lru_cache` сверху, объект `Settings` будет создан только один раз — при первом вызове. ✔️ |
||||
|
|
||||
{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *} |
{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} |
||||
|
|
||||
Затем при любых последующих вызовах `get_settings()` в зависимостях для следующих запросов, вместо выполнения внутреннего кода `get_settings()` и создания нового объекта `Settings`, будет возвращаться тот же объект, что был возвращен при первом вызове, снова и снова. |
Затем при любых последующих вызовах `get_settings()` в зависимостях для следующих запросов, вместо выполнения внутреннего кода `get_settings()` и создания нового объекта `Settings`, будет возвращаться тот же объект, что был возвращен при первом вызове, снова и снова. |
||||
|
|
||||
|
|||||
@ -1,13 +1,13 @@ |
|||||
# Как сделать — Рецепты { #how-to-recipes } |
# Как сделать — Рецепты { #how-to-recipes } |
||||
|
|
||||
Здесь вы найдете разные рецепты и руководства «как сделать» по различным темам. |
Здесь вы найдете разные рецепты и руководства «как сделать» по **различным темам**. |
||||
|
|
||||
Большинство из этих идей более-менее независимы, и в большинстве случаев вам стоит изучать их только если они напрямую относятся к вашему проекту. |
Большинство из этих идей более-менее **независимы**, и в большинстве случаев вам стоит изучать их только если они напрямую относятся к **вашему проекту**. |
||||
|
|
||||
Если что-то кажется интересным и полезным для вашего проекта, смело изучайте; в противном случае, вероятно, можно просто пропустить. |
Если что-то кажется интересным и полезным для вашего проекта, смело изучайте; в противном случае, вероятно, можно просто пропустить. |
||||
|
|
||||
/// tip | Совет |
/// tip | Совет |
||||
|
|
||||
Если вы хотите изучить FastAPI структурированно (рекомендуется), вместо этого читайте [Учебник — Руководство пользователя](../tutorial/index.md){.internal-link target=_blank} по главам. |
Если вы хотите **изучить FastAPI** структурированно (рекомендуется), вместо этого читайте [Учебник — Руководство пользователя](../tutorial/index.md){.internal-link target=_blank} по главам. |
||||
|
|
||||
/// |
/// |
||||
|
|||||
Loading…
Reference in new issue