diff --git a/docs/ru/docs/tutorial/extra-models.md b/docs/ru/docs/tutorial/extra-models.md
new file mode 100644
index 000000000..a346f7432
--- /dev/null
+++ b/docs/ru/docs/tutorial/extra-models.md
@@ -0,0 +1,252 @@
+# Дополнительные модели
+
+В продолжение прошлого примера будет уже обычным делом иметь несколько связанных между собой моделей.
+
+Это особенно применимо в случае моделей пользователя, потому что:
+
+* **Модель для ввода** должна иметь возможность содержать пароль.
+* **Модель для вывода** не должна содержать пароль.
+* **Модель для базы данных**, возможно, должна содержать хэшированный пароль.
+
+!!! danger "Внимание"
+ Никогда не храните пароли пользователей в чистом виде. Всегда храните "безопасный хэш", который вы затем сможете проверить.
+
+ Если вам это не знакомо, вы можете узнать про "хэш пароля" в [главах о безопасности](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}.
+
+## Множественные модели
+
+Ниже изложена основная идея того, как могут выглядеть эти модели с полями для паролей, а также описаны места, где они используются:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="7 9 14 20 22 27-28 31-33 38-39"
+ {!> ../../../docs_src/extra_models/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
+ {!> ../../../docs_src/extra_models/tutorial001.py!}
+ ```
+
+### Про `**user_in.dict()`
+
+#### `.dict()` из Pydantic
+
+`user_in` - это Pydantic-модель класса `UserIn`.
+
+У Pydantic-моделей есть метод `.dict()`, который возвращает `dict` с данными модели.
+
+Поэтому, если мы создадим Pydantic-объект `user_in` таким способом:
+
+```Python
+user_in = UserIn(username="john", password="secret", email="john.doe@example.com")
+```
+
+и затем вызовем:
+
+```Python
+user_dict = user_in.dict()
+```
+
+то теперь у нас есть `dict` с данными модели в переменной `user_dict` (это `dict` вместо объекта Pydantic-модели).
+
+И если мы вызовем:
+
+```Python
+print(user_dict)
+```
+
+мы можем получить `dict` с такими данными:
+
+```Python
+{
+ 'username': 'john',
+ 'password': 'secret',
+ 'email': 'john.doe@example.com',
+ 'full_name': None,
+}
+```
+
+#### Распаковка `dict`
+
+Если мы возьмём `dict` наподобие `user_dict` и передадим его в функцию (или класс), используя `**user_dict`, Python распакует его. Он передаст ключи и значения `user_dict` напрямую как аргументы типа ключ-значение.
+
+Поэтому, продолжая описанный выше пример с `user_dict`, написание такого кода:
+
+```Python
+UserInDB(**user_dict)
+```
+
+Будет работать так же, как примерно такой код:
+
+```Python
+UserInDB(
+ username="john",
+ password="secret",
+ email="john.doe@example.com",
+ full_name=None,
+)
+```
+
+Или, если для большей точности мы напрямую используем `user_dict` с любым потенциальным содержимым, то этот пример будет выглядеть так:
+
+```Python
+UserInDB(
+ username = user_dict["username"],
+ password = user_dict["password"],
+ email = user_dict["email"],
+ full_name = user_dict["full_name"],
+)
+```
+
+#### Pydantic-модель из содержимого другой модели
+
+Как в примере выше мы получили `user_dict` из `user_in.dict()`, этот код:
+
+```Python
+user_dict = user_in.dict()
+UserInDB(**user_dict)
+```
+
+будет равнозначен такому:
+
+```Python
+UserInDB(**user_in.dict())
+```
+
+...потому что `user_in.dict()` - это `dict`, и затем мы указываем, чтобы Python его "распаковал", когда передаём его в `UserInDB` и ставим перед ним `**`.
+
+Таким образом мы получаем Pydantic-модель на основе данных из другой Pydantic-модели.
+
+#### Распаковка `dict` и дополнительные именованные аргументы
+
+И затем, если мы добавим дополнительный именованный аргумент `hashed_password=hashed_password` как здесь:
+
+```Python
+UserInDB(**user_in.dict(), hashed_password=hashed_password)
+```
+
+... то мы получим что-то подобное:
+
+```Python
+UserInDB(
+ username = user_dict["username"],
+ password = user_dict["password"],
+ email = user_dict["email"],
+ full_name = user_dict["full_name"],
+ hashed_password = hashed_password,
+)
+```
+
+!!! warning "Предупреждение"
+ Цель использованных в примере вспомогательных функций - не более чем демонстрация возможных операций с данными, но, конечно, они не обеспечивают настоящую безопасность.
+
+## Сократите дублирование
+
+Сокращение дублирования кода - это одна из главных идей **FastAPI**.
+
+Поскольку дублирование кода повышает риск появления багов, проблем с безопасностью, проблем десинхронизации кода (когда вы обновляете код в одном месте, но не обновляете в другом), и т.д.
+
+А все описанные выше модели используют много общих данных и дублируют названия атрибутов и типов.
+
+Мы можем это улучшить.
+
+Мы можем определить модель `UserBase`, которая будет базовой для остальных моделей. И затем мы можем создать подклассы этой модели, которые будут наследовать её атрибуты (объявления типов, валидацию, и т.п.).
+
+Все операции конвертации, валидации, документации, и т.п. будут по-прежнему работать нормально.
+
+В этом случае мы можем определить только различия между моделями (с `password` в чистом виде, с `hashed_password` и без пароля):
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="7 13-14 17-18 21-22"
+ {!> ../../../docs_src/extra_models/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 15-16 19-20 23-24"
+ {!> ../../../docs_src/extra_models/tutorial002.py!}
+ ```
+
+## `Union` или `anyOf`
+
+Вы можете определить ответ как `Union` из двух типов. Это означает, что ответ должен соответствовать одному из них.
+
+Он будет определён в OpenAPI как `anyOf`.
+
+Для этого используйте стандартные аннотации типов в Python `typing.Union`:
+
+!!! note "Примечание"
+ При объявлении `Union`, сначала указывайте наиболее детальные типы, затем менее детальные. В примере ниже более детальный `PlaneItem` стоит перед `CarItem` в `Union[PlaneItem, CarItem]`.
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="1 14-15 18-20 33"
+ {!> ../../../docs_src/extra_models/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 14-15 18-20 33"
+ {!> ../../../docs_src/extra_models/tutorial003.py!}
+ ```
+
+### `Union` в Python 3.10
+
+В этом примере мы передаём `Union[PlaneItem, CarItem]` в качестве значения аргумента `response_model`.
+
+Поскольку мы передаём его как **значение аргумента** вместо того, чтобы поместить его в **аннотацию типа**, нам придётся использовать `Union` даже в Python 3.10.
+
+Если оно было бы указано в аннотации типа, то мы могли бы использовать вертикальную черту как в примере:
+
+```Python
+some_variable: PlaneItem | CarItem
+```
+
+Но если мы помещаем его в `response_model=PlaneItem | CarItem` мы получим ошибку, потому что Python попытается произвести **некорректную операцию** между `PlaneItem` и `CarItem` вместо того, чтобы интерпретировать это как аннотацию типа.
+
+## Список моделей
+
+Таким же образом вы можете определять ответы как списки объектов.
+
+Для этого используйте `typing.List` из стандартной библиотеки Python (или просто `list` в Python 3.9 и выше):
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/extra_models/tutorial004_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 20"
+ {!> ../../../docs_src/extra_models/tutorial004.py!}
+ ```
+
+## Ответ с произвольным `dict`
+
+Вы также можете определить ответ, используя произвольный одноуровневый `dict` и определяя только типы ключей и значений без использования Pydantic-моделей.
+
+Это полезно, если вы заранее не знаете корректных названий полей/атрибутов (которые будут нужны при использовании Pydantic-модели).
+
+В этом случае вы можете использовать `typing.Dict` (или просто `dict` в Python 3.9 и выше):
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="6"
+ {!> ../../../docs_src/extra_models/tutorial005_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 8"
+ {!> ../../../docs_src/extra_models/tutorial005.py!}
+ ```
+
+## Резюме
+
+Используйте несколько Pydantic-моделей и свободно применяйте наследование для каждой из них.
+
+Вам не обязательно иметь единственную модель данных для каждой сущности, если эта сущность должна иметь возможность быть в разных "состояниях". Как в случае с "сущностью" пользователя, у которого есть состояния с полями `password`, `password_hash` и без пароля.
diff --git a/docs/ru/mkdocs.yml b/docs/ru/mkdocs.yml
index 7b8e351f8..24ab15726 100644
--- a/docs/ru/mkdocs.yml
+++ b/docs/ru/mkdocs.yml
@@ -77,6 +77,7 @@ nav:
- tutorial/extra-data-types.md
- tutorial/cookie-params.md
- tutorial/testing.md
+ - tutorial/extra-models.md
- tutorial/response-status-code.md
- tutorial/query-params.md
- tutorial/body-multiple-params.md