diff --git a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md index fe18f1f1d..069732fb3 100644 --- a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md @@ -17,6 +17,8 @@ To do this, use `yield` instead of `return`, and write the extra steps after. In fact, FastAPI uses those two decorators internally. + And if you have a context manager already, you can use it as a dependency, too. + ## A database dependency with `yield` For example, you could use this to create a database session and close it after finishing. @@ -222,32 +224,38 @@ When the `with` block finishes, it makes sure to close the file, even if there w When you create a dependency with `yield`, **FastAPI** will internally convert it to a context manager, and combine it with some other related tools. -### Using context managers in dependencies with `yield` +## Context Managers as dependencies + +You don’t have to create a Context Manager to use FastAPI dependencies. + +But sometimes you might want to use a dependency both inside and outside FastAPI. For example, you might want to connect to a database in a DB migration script. You can create a Context Manager manually then: + +```Python +{!../../../docs_src/dependencies/tutorial010_ctx.py!} +``` + +This way you can use it with `Depends()` in your app, and as a regular Context Manager everywhere else: + +```Python +{!../../../docs_src/dependencies/tutorial010_ctx_usage.py!} +``` + + +### Defining Context Managers as classes !!! warning This is, more or less, an "advanced" idea. If you are just starting with **FastAPI** you might want to skip it for now. -In Python, you can create Context Managers by creating a class with two methods: `__enter__()` and `__exit__()`. +You can also create Context Managers by creating a class with two methods: `__enter__()` and `__exit__()`. -You can also use them inside of **FastAPI** dependencies with `yield` by using -`with` or `async with` statements inside of the dependency function: +Like the Context Managers created with `contextlib`, you can use them inside of **FastAPI** dependencies directly: ```Python hl_lines="1-9 13" {!../../../docs_src/dependencies/tutorial010.py!} ``` -!!! tip - Another way to create a context manager is with: - - * `@contextlib.contextmanager` or - * `@contextlib.asynccontextmanager` - - using them to decorate a function with a single `yield`. - - That's what **FastAPI** uses internally for dependencies with `yield`. - But you don't have to use the decorators for FastAPI dependencies (and you shouldn't). - - FastAPI will do it for you internally. +!!! note "Technical Details" + Internally, FastAPI calls the dependency function and then checks if the result has either an `__enter__()` or an `__aenter__()` method. If that’s the case, it will treat it as a context manager. diff --git a/docs_src/dependencies/tutorial010.py b/docs_src/dependencies/tutorial010.py index c27f1b170..fcf80e698 100644 --- a/docs_src/dependencies/tutorial010.py +++ b/docs_src/dependencies/tutorial010.py @@ -9,6 +9,6 @@ class MySuperContextManager: self.db.close() -async def get_db(): - with MySuperContextManager() as db: - yield db +@app.get("/") +async def get_root(db: Annotated[DBSession, Depends(MySuperContextManager)]): + ... diff --git a/docs_src/dependencies/tutorial010_ctx.py b/docs_src/dependencies/tutorial010_ctx.py new file mode 100644 index 000000000..71f6aa284 --- /dev/null +++ b/docs_src/dependencies/tutorial010_ctx.py @@ -0,0 +1,9 @@ +from contextlib import asynccontextmanager + +@asynccontextmanager +async def get_db(): + db = DBSession() + try: + yield db + finally: + db.close() diff --git a/docs_src/dependencies/tutorial010_ctx_usage.py b/docs_src/dependencies/tutorial010_ctx_usage.py new file mode 100644 index 000000000..11a3ccf2e --- /dev/null +++ b/docs_src/dependencies/tutorial010_ctx_usage.py @@ -0,0 +1,3 @@ +async def migrate(): + with get_db() as db: + ...