Browse Source

Merge pull request #1 from ceb10n/master

update branch to continue pt translations
pull/14228/head
Rafael de Oliveira Marques 8 months ago
committed by GitHub
parent
commit
5c71dd0d50
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 12
      docs/de/docs/advanced/advanced-dependencies.md
  2. 45
      docs/de/docs/tutorial/dependencies/dependencies-with-yield.md
  3. 11
      docs/en/docs/release-notes.md
  4. 12
      docs/ru/docs/advanced/advanced-dependencies.md
  5. 133
      docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md
  6. 45
      docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md
  7. 2
      fastapi/__init__.py
  8. 5
      fastapi/dependencies/utils.py
  9. 64
      tests/test_dependency_yield_scope.py

12
docs/de/docs/advanced/advanced-dependencies.md

@ -70,12 +70,22 @@ Wenn Sie das hier alles verstanden haben, wissen Sie bereits, wie diese Sicherhe
Sie benötigen diese technischen Details höchstwahrscheinlich nicht.
Diese Details sind hauptsächlich nützlich, wenn Sie eine FastAPI-Anwendung haben, die älter als 0.118.0 ist, und Sie auf Probleme mit Abhängigkeiten mit `yield` stoßen.
Diese Details sind hauptsächlich nützlich, wenn Sie eine FastAPI-Anwendung haben, die älter als 0.121.0 ist, und Sie auf Probleme mit Abhängigkeiten mit `yield` stoßen.
///
Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben, hier ist eine Zusammenfassung der Änderungen.
### Abhängigkeiten mit `yield` und `scope` { #dependencies-with-yield-and-scope }
In Version 0.121.0 hat FastAPI Unterstützung für `Depends(scope="function")` für Abhängigkeiten mit `yield` hinzugefügt.
Mit `Depends(scope="function")` wird der Exit-Code nach `yield` direkt nach dem Ende der *Pfadoperation-Funktion* ausgeführt, bevor die Response an den Client gesendet wird.
Und bei Verwendung von `Depends(scope="request")` (dem Default) wird der Exit-Code nach `yield` ausgeführt, nachdem die Response gesendet wurde.
Mehr dazu finden Sie in der Dokumentation zu [Abhängigkeiten mit `yield` – Frühes Beenden und `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope).
### Abhängigkeiten mit `yield` und `StreamingResponse`, Technische Details { #dependencies-with-yield-and-streamingresponse-technical-details }
Vor FastAPI 0.118.0 wurde bei Verwendung einer Abhängigkeit mit `yield` der Exit-Code nach der *Pfadoperation-Funktion* ausgeführt, aber unmittelbar bevor die Response gesendet wurde.

45
docs/de/docs/tutorial/dependencies/dependencies-with-yield.md

@ -184,6 +184,51 @@ Wenn Sie in dem Code der *Pfadoperation-Funktion* irgendeine Exception auslösen
///
## Frühes Beenden und `scope` { #early-exit-and-scope }
Normalerweise wird der Exit-Code von Abhängigkeiten mit `yield` ausgeführt **nachdem die Response** an den Client gesendet wurde.
Wenn Sie aber wissen, dass Sie die Abhängigkeit nach der Rückkehr aus der *Pfadoperation-Funktion* nicht mehr benötigen, können Sie `Depends(scope="function")` verwenden, um FastAPI mitzuteilen, dass es die Abhängigkeit nach der Rückkehr aus der *Pfadoperation-Funktion* schließen soll, jedoch **bevor** die **Response gesendet wird**.
{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
`Depends()` erhält einen `scope`-Parameter, der sein kann:
* `"function"`: startet die Abhängigkeit vor der *Pfadoperation-Funktion*, die den Request bearbeitet, beendet die Abhängigkeit nach dem Ende der *Pfadoperation-Funktion*, aber **bevor** die Response an den Client zurückgesendet wird. Die Abhängigkeitsfunktion wird also **um** die *Pfadoperation-**Funktion*** **herum** ausgeführt.
* `"request"`: startet die Abhängigkeit vor der *Pfadoperation-Funktion*, die den Request bearbeitet (ähnlich wie bei `"function"`), beendet sie jedoch **nachdem** die Response an den Client zurückgesendet wurde. Die Abhängigkeitsfunktion wird also **um** den **Request**- und Response-Zyklus **herum** ausgeführt.
Wenn nicht angegeben und die Abhängigkeit `yield` hat, hat sie standardmäßig einen `scope` von `"request"`.
### `scope` für Unterabhängigkeiten { #scope-for-sub-dependencies }
Wenn Sie eine Abhängigkeit mit `scope="request"` (dem Default) deklarieren, muss jede Unterabhängigkeit ebenfalls einen `scope` von `"request"` haben.
Eine Abhängigkeit mit `scope` von `"function"` kann jedoch Abhängigkeiten mit `scope` von `"function"` und `scope` von `"request"` haben.
Das liegt daran, dass jede Abhängigkeit in der Lage sein muss, ihren Exit-Code vor den Unterabhängigkeiten auszuführen, da sie diese während ihres Exit-Codes möglicherweise noch verwenden muss.
```mermaid
sequenceDiagram
participant client as Client
participant dep_req as Abhängigkeit scope="request"
participant dep_func as Abhängigkeit scope="function"
participant operation as Pfadoperation
client ->> dep_req: Startet den Request
Note over dep_req: Führt den Code bis zum yield aus
dep_req ->> dep_func: Reicht Abhängigkeit weiter
Note over dep_func: Führt den Code bis zum yield aus
dep_func ->> operation: Führt Pfadoperation mit Abhängigkeit aus
operation ->> dep_func: Kehrt aus Pfadoperation zurück
Note over dep_func: Führt Code nach yield aus
Note over dep_func: ✅ Abhängigkeit geschlossen
dep_func ->> client: Sendet Response an Client
Note over client: Response gesendet
Note over dep_req: Führt Code nach yield aus
Note over dep_req: ✅ Abhängigkeit geschlossen
```
## Abhängigkeiten mit `yield`, `HTTPException`, `except` und Hintergrundtasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben.

11
docs/en/docs/release-notes.md

@ -7,6 +7,17 @@ hide:
## Latest Changes
### Translations
* 🌐 Sync Russian docs. PR [#14331](https://github.com/fastapi/fastapi/pull/14331) by [@YuriiMotov](https://github.com/YuriiMotov).
* 🌐 Sync German docs. PR [#14317](https://github.com/fastapi/fastapi/pull/14317) by [@nilslindemann](https://github.com/nilslindemann).
## 0.121.1
### Fixes
* 🐛 Fix `Depends(func, scope='function')` for top level (parameterless) dependencies. PR [#14301](https://github.com/fastapi/fastapi/pull/14301) by [@luzzodev](https://github.com/luzzodev).
### Docs
* 📝 Upate docs for advanced dependencies with `yield`, noting the changes in 0.121.0, adding `scope`. PR [#14287](https://github.com/fastapi/fastapi/pull/14287) by [@tiangolo](https://github.com/tiangolo).

12
docs/ru/docs/advanced/advanced-dependencies.md

@ -70,12 +70,22 @@ checker(q="somequery")
Скорее всего, вам не понадобятся эти технические детали.
Они полезны главным образом, если у вас было приложение FastAPI версии ниже 0.118.0 и вы столкнулись с проблемами зависимостей с `yield`.
Они полезны главным образом, если у вас было приложение FastAPI версии ниже 0.121.0 и вы столкнулись с проблемами зависимостей с `yield`.
///
Зависимости с `yield` со временем изменялись, чтобы учитывать разные случаи применения и исправлять проблемы. Ниже — краткое резюме изменений.
### Зависимости с `yield` и `scope` { #dependencies-with-yield-and-scope }
В версии 0.121.0 FastAPI добавил поддержку `Depends(scope="function")` для зависимостей с `yield`.
При использовании `Depends(scope="function")` код после `yield` выполняется сразу после завершения *функции-обработчика пути*, до отправки ответа клиенту.
А при использовании `Depends(scope="request")` (значение по умолчанию) код после `yield` выполняется после отправки ответа.
Подробнее читайте в документации: [Зависимости с `yield` — раннее завершение и `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope).
### Зависимости с `yield` и `StreamingResponse`, технические детали { #dependencies-with-yield-and-streamingresponse-technical-details }
До FastAPI 0.118.0, если вы использовали зависимость с `yield`, код после `yield` выполнялся после возврата из *функции-обработчика пути*, но прямо перед отправкой ответа.

133
docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md

@ -0,0 +1,133 @@
# Миграция с Pydantic v1 на Pydantic v2 { #migrate-from-pydantic-v1-to-pydantic-v2 }
Если у вас старое приложение FastAPI, возможно, вы используете Pydantic версии 1.
FastAPI поддерживает и Pydantic v1, и v2 начиная с версии 0.100.0.
Если у вас был установлен Pydantic v2, использовался он. Если вместо этого был установлен Pydantic v1 — использовался он.
Сейчас Pydantic v1 объявлен устаревшим, и поддержка его будет удалена в следующих версиях FastAPI, поэтому вам следует **перейти на Pydantic v2**. Так вы получите последние возможности, улучшения и исправления.
/// warning | Предупреждение
Кроме того, команда Pydantic прекратила поддержку Pydantic v1 для последних версий Python, начиная с **Python 3.14**.
Если вы хотите использовать последние возможности Python, вам нужно убедиться, что вы используете Pydantic v2.
///
Если у вас старое приложение FastAPI с Pydantic v1, здесь я покажу, как мигрировать на Pydantic v2, и **новые возможности в FastAPI 0.119.0**, которые помогут выполнить постепенную миграцию.
## Официальное руководство { #official-guide }
У Pydantic есть официальное <a href="https://docs.pydantic.dev/latest/migration/" class="external-link" target="_blank">руководство по миграции</a> с v1 на v2.
Там также описано, что изменилось, как валидации стали более корректными и строгими, возможные нюансы и т.д.
Прочитайте его, чтобы лучше понять, что изменилось.
## Тесты { #tests }
Убедитесь, что у вас есть [тесты](../tutorial/testing.md){.internal-link target=_blank} для вашего приложения и что вы запускаете их в системе непрерывной интеграции (CI).
Так вы сможете выполнить обновление и убедиться, что всё работает как ожидается.
## `bump-pydantic` { #bump-pydantic }
Во многих случаях, когда вы используете обычные Pydantic‑модели без пользовательских настроек, вы сможете автоматизировать большую часть процесса миграции с Pydantic v1 на Pydantic v2.
Вы можете использовать <a href="https://github.com/pydantic/bump-pydantic" class="external-link" target="_blank">`bump-pydantic`</a> от той же команды Pydantic.
Этот инструмент поможет автоматически внести большую часть необходимых изменений в код.
После этого запустите тесты и проверьте, что всё работает. Если да — на этом всё. 😎
## Pydantic v1 в v2 { #pydantic-v1-in-v2 }
Pydantic v2 включает всё из Pydantic v1 как подмодуль `pydantic.v1`.
Это означает, что вы можете установить последнюю версию Pydantic v2 и импортировать и использовать старые компоненты Pydantic v1 из этого подмодуля так, как если бы у вас был установлен старый Pydantic v1.
{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *}
### Поддержка FastAPI для Pydantic v1 внутри v2 { #fastapi-support-for-pydantic-v1-in-v2 }
Начиная с FastAPI 0.119.0, есть также частичная поддержка Pydantic v1 в составе Pydantic v2, чтобы упростить миграцию на v2.
Таким образом, вы можете обновить Pydantic до последней версии 2 и сменить импорты на подмодуль `pydantic.v1` — во многих случаях всё просто заработает.
{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *}
/// warning | Предупреждение
Имейте в виду, что так как команда Pydantic больше не поддерживает Pydantic v1 в последних версиях Python, начиная с Python 3.14, использование `pydantic.v1` также не поддерживается в Python 3.14 и выше.
///
### Pydantic v1 и v2 в одном приложении { #pydantic-v1-and-v2-on-the-same-app }
В Pydantic **не поддерживается** ситуация, когда в одной модели Pydantic v2 используются поля, определённые как модели Pydantic v1, и наоборот.
```mermaid
graph TB
subgraph "❌ Not Supported"
direction TB
subgraph V2["Pydantic v2 Model"]
V1Field["Pydantic v1 Model"]
end
subgraph V1["Pydantic v1 Model"]
V2Field["Pydantic v2 Model"]
end
end
style V2 fill:#f9fff3
style V1 fill:#fff6f0
style V1Field fill:#fff6f0
style V2Field fill:#f9fff3
```
…но в одном и том же приложении вы можете иметь отдельные модели на Pydantic v1 и v2.
```mermaid
graph TB
subgraph "✅ Supported"
direction TB
subgraph V2["Pydantic v2 Model"]
V2Field["Pydantic v2 Model"]
end
subgraph V1["Pydantic v1 Model"]
V1Field["Pydantic v1 Model"]
end
end
style V2 fill:#f9fff3
style V1 fill:#fff6f0
style V1Field fill:#fff6f0
style V2Field fill:#f9fff3
```
В некоторых случаях можно использовать и модели Pydantic v1, и v2 в одной и той же операции пути (обработчике пути) вашего приложения FastAPI:
{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *}
В примере выше модель входных данных — это модель Pydantic v1, а модель выходных данных (указанная в `response_model=ItemV2`) — это модель Pydantic v2.
### Параметры Pydantic v1 { #pydantic-v1-parameters }
Если вам нужно использовать некоторые специфичные для FastAPI инструменты для параметров, такие как `Body`, `Query`, `Form` и т.п., с моделями Pydantic v1, вы можете импортировать их из `fastapi.temp_pydantic_v1_params`, пока завершаете миграцию на Pydantic v2:
{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *}
### Мигрируйте по шагам { #migrate-in-steps }
/// tip | Совет
Сначала попробуйте `bump-pydantic`. Если тесты проходят и всё работает, вы справились одной командой. ✨
///
Если `bump-pydantic` не подходит для вашего случая, вы можете использовать поддержку одновременной работы моделей Pydantic v1 и v2 в одном приложении, чтобы мигрировать на Pydantic v2 постепенно.
Сначала обновите Pydantic до последней 2-й версии и измените импорты так, чтобы все ваши модели использовали `pydantic.v1`.
Затем начните мигрировать ваши модели с Pydantic v1 на v2 группами, поэтапно. 🚶

45
docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md

@ -184,6 +184,51 @@ participant tasks as Background tasks
///
## Ранний выход и `scope` { #early-exit-and-scope }
Обычно «код выхода» зависимостей с `yield` выполняется **после того, как ответ** отправлен клиенту.
Но если вы знаете, что не будете использовать зависимость после возврата из *функции-обработчика пути*, вы можете использовать `Depends(scope="function")`, чтобы сообщить FastAPI, что он должен закрыть зависимость после возврата из *функции-обработчика пути*, но **до того**, как **ответ будет отправлен**.
{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
`Depends()` принимает параметр `scope`, который может быть:
* `"function"`: начать зависимость до *функции-обработчика пути*, которая обрабатывает запрос, завершить зависимость после окончания *функции-обработчика пути*, но **до того**, как ответ будет отправлен обратно клиенту. То есть функция зависимости будет выполнена **вокруг** *функции-обработчика пути*.
* `"request"`: начать зависимость до *функции-обработчика пути*, которая обрабатывает запрос (как и при использовании `"function"`), но завершить **после** того, как ответ будет отправлен обратно клиенту. То есть функция зависимости будет выполнена **вокруг** цикла запроса (**request**) и ответа.
Если не указано и в зависимости есть `yield`, по умолчанию будет `scope` со значением `"request"`.
### `scope` для подзависимостей { #scope-for-sub-dependencies }
Когда вы объявляете зависимость с `scope="request"` (значение по умолчанию), любая подзависимость также должна иметь `scope` равный `"request"`.
Но зависимость со `scope` равным `"function"` может иметь зависимости со `scope` `"function"` и со `scope` `"request"`.
Это потому, что любая зависимость должна иметь возможность выполнить свой код выхода раньше подзависимостей, так как ей может понадобиться использовать их во время своего кода выхода.
```mermaid
sequenceDiagram
participant client as Client
participant dep_req as Зависимость scope="request"
participant dep_func as Зависимость scope="function"
participant operation as Функция-обработчик пути
client ->> dep_req: Запрос
Note over dep_req: Выполнить код до yield
dep_req ->> dep_func: Передать значение
Note over dep_func: Выполнить код до yield
dep_func ->> operation: Выполнить функцию-обработчик пути
operation ->> dep_func: Выход из функции-обработчика пути
Note over dep_func: Выполнить код после yield
Note over dep_func: ✅ Зависимость закрыта
dep_func ->> client: Отправить ответ клиенту
Note over client: Ответ отправлен
Note over dep_req: Выполнить код после yield
Note over dep_req: ✅ Зависимость закрыта
```
## Зависимости с `yield`, `HTTPException`, `except` и фоновыми задачами { #dependencies-with-yield-httpexception-except-and-background-tasks }
Зависимости с `yield` со временем эволюционировали, чтобы покрыть разные сценарии и исправить некоторые проблемы.

2
fastapi/__init__.py

@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
__version__ = "0.121.0"
__version__ = "0.121.1"
from starlette import status as status

5
fastapi/dependencies/utils.py

@ -129,7 +129,10 @@ def get_parameterless_sub_dependant(*, depends: params.Depends, path: str) -> De
if isinstance(depends, params.Security) and depends.scopes:
use_security_scopes.extend(depends.scopes)
return get_dependant(
path=path, call=depends.dependency, security_scopes=use_security_scopes
path=path,
call=depends.dependency,
scope=depends.scope,
security_scopes=use_security_scopes,
)

64
tests/test_dependency_yield_scope.py

@ -2,7 +2,7 @@ import json
from typing import Any, Tuple
import pytest
from fastapi import Depends, FastAPI
from fastapi import APIRouter, Depends, FastAPI, HTTPException
from fastapi.exceptions import FastAPIError
from fastapi.responses import StreamingResponse
from fastapi.testclient import TestClient
@ -20,6 +20,11 @@ def dep_session() -> Any:
s.open = False
def raise_after_yield() -> Any:
yield
raise HTTPException(status_code=503, detail="Exception after yield")
SessionFuncDep = Annotated[Session, Depends(dep_session, scope="function")]
SessionRequestDep = Annotated[Session, Depends(dep_session, scope="request")]
SessionDefaultDep = Annotated[Session, Depends(dep_session)]
@ -64,6 +69,12 @@ RegularSessionsDep = Annotated[
]
app = FastAPI()
router = APIRouter()
@router.get("/")
def get_index():
return {"status": "ok"}
@app.get("/function-scope")
@ -124,6 +135,18 @@ def get_regular_function_scope(sessions: RegularSessionsDep) -> Any:
return StreamingResponse(iter_data())
app.include_router(
prefix="/router-scope-function",
router=router,
dependencies=[Depends(raise_after_yield, scope="function")],
)
app.include_router(
prefix="/router-scope-request",
router=router,
dependencies=[Depends(raise_after_yield, scope="request")],
)
client = TestClient(app)
@ -182,3 +205,42 @@ def test_regular_function_scope() -> None:
data = response.json()
assert data["named_session_open"] is True
assert data["session_open"] is False
def test_router_level_dep_scope_function() -> None:
response = client.get("/router-scope-function/")
assert response.status_code == 503
assert response.json() == {"detail": "Exception after yield"}
def test_router_level_dep_scope_request() -> None:
with TestClient(app, raise_server_exceptions=False) as client:
response = client.get("/router-scope-request/")
assert response.status_code == 200
assert response.json() == {"status": "ok"}
def test_app_level_dep_scope_function() -> None:
app = FastAPI(dependencies=[Depends(raise_after_yield, scope="function")])
@app.get("/app-scope-function")
def get_app_scope_function():
return {"status": "ok"}
with TestClient(app) as client:
response = client.get("/app-scope-function")
assert response.status_code == 503
assert response.json() == {"detail": "Exception after yield"}
def test_app_level_dep_scope_request() -> None:
app = FastAPI(dependencies=[Depends(raise_after_yield, scope="request")])
@app.get("/app-scope-request")
def get_app_scope_request():
return {"status": "ok"}
with TestClient(app, raise_server_exceptions=False) as client:
response = client.get("/app-scope-request")
assert response.status_code == 200
assert response.json() == {"status": "ok"}

Loading…
Cancel
Save